diff options
754 files changed, 93919 insertions, 6132 deletions
@@ -20,3 +20,6 @@ __pycache__/ # pyenv .python-version + +# GitHub token +.pypt/gh-token diff --git a/.pypt/ghrel b/.pypt/ghrel new file mode 100755 index 0000000..26463c5 --- /dev/null +++ b/.pypt/ghrel @@ -0,0 +1,90 @@ +#!/usr/bin/env python +# -*- encoding: utf-8 -*- +# Kw’s Release Tools/Python Project Template +# GitHub Releases Creator +# Copyright © 2013-2015, Chris Warrick. +# All rights reserved. +# +# 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. +# +# 3. Neither the name of the author of this software nor the names of +# contributors to this software may be used to endorse or promote +# products derived from this software without specific prior written +# consent. +# +# 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. + +# Arguments: +# FILE BASEDIR REPO TAG + +""" +Create GitHub releases out of changelogs. + +Usage: .pypt/commitlog FILE BASEDIR REPO TAG, where + FILE is the path to the file to use, which can be + a plain .md file or a CMFN file, + BASEDIR is the project directory, + REPO is the full GitHub repository name (user/repo), + TAG is the tag to write to. + All paths should be absolute. +""" + +import re +import requests +import json +from os.path import join as pjoin +from sys import argv + +_script, FILE, BASEDIR, REPO, TAG = argv + +with open(pjoin(BASEDIR, '.pypt', 'gh-token')) as fh: + TOKEN = fh.read().strip() + +HEADERS = { + 'User-Agent': 'Kwpolska/python-project-template', + 'Authorization': 'token ' + TOKEN, +} + +with open(FILE) as fh: + fdata = fh.read() + e = re.findall( + '#~ CHANGELOG MESSAGE START ~#\n(.*?)\n#~ CHANGELOG MESSAGE END ~#', + fdata, flags=re.S) + + if e: + # parse as a CMFN file, replace backticks (reST->Markdown) + message = e[0].replace('``', '`') + else: + # parse as a plain Markdown file + message = fdata + + +r = requests.post( + 'https://api.github.com/repos/{0}/releases'.format(REPO), + data=json.dumps({'tag_name': TAG, 'body': message}), + headers=HEADERS) + +if r.status_code == 201: + print("GitHub Release created: {0}".format(r.json()['url'])) +else: + print("GitHub Release failed: {0}".format(r.text)) + exit(1) diff --git a/.travis.yml b/.travis.yml index 61609aa..123e481 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,6 @@ before_install: language: python cache: apt python: - - "2.6" - "2.7" - "3.3" - "3.4" @@ -41,3 +40,5 @@ notifications: - "%{repository}#%{build_number} (%{branch} - %{commit} : %{author}): %{message}" - "Change view: %{compare_url}" - "Build details: %{build_url}" + skip_join: true + use_notice: true diff --git a/AUTHORS.txt b/AUTHORS.txt index dd7381e..0f2f8c8 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -1,78 +1,106 @@ -These are the people who have committed code according to GitHub. -There is probably someone missing if he sent me code directly, and -for that I am sorry because I believe in giving credit. -If you are here and prefer to be listed in a different way, just -do a PR :-) - - -- Roberto Alsina - - +Agustin Henze <https://github.com/agustinhenze> Alberto Berti <https://github.com/azazel75> +Alex Popescu <https://github.com/al3xandru> +Alex Walters <https://github.com/tritium21> +Andreas Linz <https://github.com/KLINGTdotNET> +Areski Belaid <https://github.com/areski> Aru Sahni <https://github.com/arusahni> -Bluerise <https://github.com/Bluerise> -Chris “Kwpolska” Warrick <https://github.com/Kwpolska> +Aurelien Naldi <https://github.com/aurelien-naldi> +Ben Mather <https://github.com/bwhmather> +Boris Kaul <https://github.com/localvoid> +Brandon W. Maister <https://github.com/quodlibetor> +Bussonnier Matthias <https://gtihub.com/carreau> +Carsten Grohmann <https://github.com/CarstenGrohmann> +Casey M. Bessette <https://github.com/caseybessette> +Chris Lee <https://github.com/clee> +Chris Warrick <https://github.com/Kwpolska> +Claudio Canepa <https://github.com/ccanepa> +Damien Tournoud <https://github.com/damz> +Damián Avila <https://github.com/damianavila> Daniel Aleksandersen <https://github.com/Aeyoun> +Daniel Devine <https://github.com/DDevine> +Daniel F. Moisset <https://github.com/dmoisset> +David Beath <https://github.com/DBeath> +Dhruv Baldawa <https://github.com/dhruvbaldawa> +Dirk Engling <https://github.com/erdgeist> Dmitry Verkhoturov <https://github.com/paskal> -DoctorMalboro <https://github.com/DoctorMalboro> +Duncan Lock <https://github.com/dflock> +Edinei Cavalcanti <https://github.com/neiesc> Eduardo Schettino <https://github.com/schettino72> +Edwin Steele <https://github.com/edwinsteele> +Emilien Klein <https://github.com/e2jk> Evgeni Golov <https://github.com/evgeni> +Felix Fontein <https://github.com/felixfontein> +Felix Schwarz <https://github.com/FelixSchwarz> +Grzegorz Śliwiński <https://github.com/fizyk> +Guillermo O. Freschi <https://github.com/Tordek> +Hardening <https://github.com/hardening> +Ivan Teoh <https://github.com/ivanteoh> +John Kristensen <https://github.com/jerrykan> +Joshua Barratt <https://github.com/jbarratt> +Juan Pedro Fisanotti <https://github.com/fisadev> +Kade For <https://github.com/kadefor> Kay Hayen <https://github.com/kayhayen> +Leandro Poblet <https://github.com/DoctorMalboro> +Luis Miguel Morillas <https://github.com/lmorillas> +Manuel Kaufmann <https://github.com/humitos> +Marcelo MD <https://github.com/marcelomd> +Marcos Dione <https://github.com/StyXman> +Mariano Guerra <https://github.com/marianoguerra> +Mario Pozzo <https://github.com/camboris> +Mark Eichin <https://github.com/eichin> +Martin Bless <https://github.com/marble> +Martin Wimpress <https://github.com/wimpr1m> +Martín Gaitán <https://github.com/mgaitan> +Matias Novoa <https://github.com/mattgaviota> +Michael Joseph <https://github.com/michaeljoseph> +Michael McNeil Forbes <https://github.com/mforbes> +Michal Petrucha <https://github.com/koniiiik> +Miguel Ángel García <https://github.com/magmax> +Neil MartinsenBurrell <https://github.com/neilmb> Niko Wenselowski <https://github.com/okin> +Nikola Kotur <https://github.com/kotnik> Ondřej Grover <https://github.com/smartass101> +Onno Broekmans <https://github.com/onnodb> +Pablo Seminario <https://github.com/pabluk> +Patrick Wildt <https://github.com/Bluerise> +Paul Ivanov <https://github.com/ivanov> +Pelle Nilsson <https://github.com/pellenilsson> +Pierpaolo Da Fieno <https://github.com/numshub> +Puneeth Chaganti <https://github.com/punchagan> Raimon Esteve <https://github.com/raimonesteve> +Ramiro Morales <https://github.com/ramiro> Roberto Alsina <https://github.com/ralsina> +Rodrigo Bistolfi <https://github.com/rbistolfi> +Roger Binns <https://github.com/rogerbinns> +Roman Faizullin <https://github.com/faizrr> Roman Imankulov <https://github.com/imankulov> +Santiago Pestarini <https://github.com/quijot> Sean Pue <https://github.com/seanpue> -StyXman <https://github.com/StyXman> +Simon van der Veldt <https://github.com/simonvanderveldt> +Stefan Näwe <https://github.com/snaewe> +Thibauld Nion <https://github.com/tibonihoo> +Thomas Burette <https://github.com/tburette> Tim Chase <https://github.com/Gumnos> -Tordek <https://github.com/Tordek> +Tolu Sonaike <https://github.com/tolusonaike> Troy Toman <https://github.com/troytoman> +Udo Spallek <https://github.com/udono> +Yaşar Arabacı <https://github.com/yasar11732> +Yasuhiko Shiga <https://github.com/quoth> Zhaojun Meng <https://github.com/zhaojunmeng> -agustinhenze <https://github.com/agustinhenze> -areski <https://github.com/areski> -bwhmather <https://github.com/bwhmather> -camboris <https://github.com/camboris> -Claudio Canepa <https://github.com/ccanepa> -clee <https://github.com/clee> -damianavila <https://github.com/damianavila> dastagg <https://github.com/dastagg> -dflock <https://github.com/dflock> -dhruvbaldawa <https://github.com/dhruvbaldawa> -dmoisset <https://github.com/dmoisset> -edwinsteele <https://github.com/edwinsteele> -ermeaney <https://github.com/ermeney> -fisadev <https://github.com/fisadev> -fizyk <https://github.com/fizyk> -ivanov <https://github.com/ivanov> -ivanteoh <https://github.com/ivanteoh> -jerrykan <https://github.com/jerrykan> -kadefor <https://github.com/kadefor> -koniiiik <https://github.com/koniiiik> -kotnik <https://github.com/kotnik> -localvoid <https://github.com/localvoid> -marcelomd <https://github.com/marcelomd> -marianoguerra <https://github.com/marianoguerra> -mattgaviota <https://github.com/mattgaviota> -mgaitan <https://github.com/mgaitan> +dastagg <https://github.com/dastagg> +ermeaney <https://github.com/ermeaney> +follower <https://github.com/follower> +lbiaggi <https://github.com/lbiaggi> mrabbitt <https://github.com/mrabbitt> -neiesc <https://github.com/neiesc> -neilmb <https://github.com/neilmb> +nlaurens <https://github.com/nlaurens> notfoss <https://github.com/notfoss> -numshub <https://github.com/numshub> -onnodb <https://github.com/onnodb> -pabluk <https://github.com/pabluk> -punchagan <https://github.com/punchagan> +phora <https://github.com/phora> +pmav99 <https://github.com/pmav99> pwm1234 <https://github.com/pwm1234> -quijot <https://github.com/quijot> -quodlibetor <https://github.com/quodlibetor> -quoth <https://github.com/quoth> rafacarrascosa <https://github.com/rafacarrascosa> -rbistolfi <https://github.com/rbistolfi> -snaewe <https://github.com/snaewe> -tolusonaike <https://github.com/tolusonaike> -Thomas Burette <https://github.com/tburette> -wimpr1m <https://github.com/wimpr1m> yarko <https://github.com/yarko> -Alex Walters <https://github.com/tritium21> -Carsten Grohmann <https://github.com/CarstenGrohmann> -Aurelien Naldi <https://github.com/aurelien-naldi> +小明 <https://github.com/dongweiming> +Brad Miller <https://github.com/bnmnetp> + diff --git a/CHANGES.txt b/CHANGES.txt index 79a8f3b..ea3cd93 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,339 @@ +New in v7.6.0 +============= + +Features +-------- + +* Translate ``Write your post here.`` to default language (Issue #1621) +* Enable ``PRETTY_URLS`` by default on new sites created by the wizard + (Issue #1838) +* Add ``-F``, ``--available-compilers`` option to ``nikola new_post`` + and ``nikola new_page`` (Issue #1837) +* Add print CSS to all default themes (Issue #1817) +* Support other kernels for ipynb/Jupyter using + ``nikola new_post -f ipynb@kernel`` (Issues #1774, #1834) +* Add distinct styling for the site footer in bootstrap3 +* Bootstrap v3.3.5 (Issue #1828) +* Use ``watchdog`` in ``nikola auto`` (Issue #1810) +* Add redirection for tags in Wordpress importer (Issue #1168) +* Add support for ``html_tidy_withconfig`` to use a ``tidy5.conf`` file + (Issue #1795) +* Change default tidy5 filters not to drop empty elements (Issue #1795) +* Apply per-post filters via metadata (Issue #914) + +Bugfixes +-------- + +* Nikola auto was broken in python 3 (Issue #1830) +* Read configuration when importing into an existing site (Issue #1823) +* Don’t crash on non-UTF-8 files during sitemap generation (Issue #1842) +* Unnecessary rebuilds of yearly archives (Issue #1833) +* Quietly ignore non-existent files in ``nikola check -l`` (Issue #1831) +* Don’t rebuild all tag or category pages when changing tag/category descriptions +* Fix crash in wordpress code importer (Issue #1819) +* Call correct command in ``nikola auto`` + +New in v7.5.1 +============= + +Features +-------- + +* Suggest misspelled commands (Issue #1807) +* New implementation of the ``nikola auto`` command +* ``requests`` is now required for all Nikola sites +* New ``nikola version --check`` option (Issue #1767) + +Bugfixes +-------- + +* Support pure markdown posts in WP import (Issue #484) +* Make auto shutdown with ctrl-c (Issue #1811) +* Log properly in ``nikola auto`` (Issue #1812) +* Handle rare gettz failure (Issue #1806) +* Handle missing dependencies better in auto plugin (Issues #1803, #1809) +* IDNA mixing unicode/bytes in python 3 (Issue #1802) +* Cleaner splitting of metadata in onefile posts (Issue #973) +* It's markdown extra, not extras (Issue #1799) + +New in v7.5.0 +============= + +Features +-------- + +* Make default themes more accessible (Issue #377) +* Add ipython support to the default themes (Issue #1782) +* Automatically mark ipynb posts/pages as requiring mathjax (Issue #1782) +* New --get-path option for ``nikola install_theme`` (Issue #1762) +* New `nikola rst2html` command (Issue #1710) +* New `nikola status` command (Issue #1740) +* Support [code] in wordpress importers (Issue #1186) +* Cleaner formatting of HTML output +* Allowing category hierarchies via new option CATEGORY_ALLOW_HIERARCHIES + (Issue #1520) + +Bugfixes +-------- + +* Dropped empty languages (fil, tl, zh_TW) +* Extract ``nikola check`` target list from actual task list instead of parsing (Issue #1758) +* Treat special-purpose “draft” tag case-insensitive +* Avoid some rebuild loops (Issue #1747) +* Better error if two posts/pages output conflict (Issue #1749) +* Scanning of posts refactored out of core (Issue #1700) +* github_deploy records lastdeploy timestamp like regular deploy +* Use a global directory for gallery images, ignoring translations (Issue #1726) +* The post-list directive only triggers rebuilds if timeline changes (Issue #1688) +* Don’t check the same remote URL more than once (Issue #1732) +* All remotely checked links resulted in incorrect warnings (`nikola check -lr`) +* Exclude `<meta content="noindex" name="robots">` from sitemaps +* new_post paths are now relative to CWD (Issue #1325) + +New in v7.4.1 +============= + +Features +-------- + +* Better handling of missing/unconfigured compilers (Issue #1704) +* New -r option for the link checker to check remote links (Issue #1684) +* Use static navbars in bootstrap3 and bootstrap themes + +Bugfixes +-------- + +* Handle strange URLs, like ed2k:// (Issue #1695) +* Fix very old metadata format support (Issue #1689) + +New in v7.4.0 +============= + +Features +-------- + +* Substitutions for RSS_LINKS_APPEND_QUERY for identifying + the source feed (feedRelUri) and the kind of feed (feedFormat). +* New option GENERATE_ATOM, off by default +* Current and archive Atom feeds for indexes; category, tag, and archive indexes (RFC-4287 and RFC-5005) +* Atom feed auto-discovery in HTML indexes and category/tag indexes +* .atom included in the sitemap index +* New post metadata "updated", inherits "date" if unset +* Allow IPv6 in `nikola auto` (Issue #1682) +* Allow IPv6 in `nikola serve` (Issue #1682) +* Set default new site URL to https://example.com/ +* Plugins can manipulate task dependencies (Issue #1679) +* LINK_CHECK_WHITELIST now works with output relative and full fs paths +* Four new filters: html_tidy_nowrap, html_tidy_wrap, html_tidy_wrap_attr, + and html_tidy_mini for prettification and minification. Requires tidy5. +* Multilingual sitemaps (Issue #1610) +* Compatibility with doit v0.28.0 (Issue #1655) +* AddThis is no longer added by default to users’ sites +* New translations (az, fil, tl, uk, zh_TW) +* Add reStructuredText transform support (Issue #1647) +* Produce Unicode output in ``nikola init`` (via Issue #1644) +* Add ``HIDDEN_TAGS`` and ``HIDDEN_CATEGORIES`` settings to hide some + tags and categories (eg. ``mathjax``) from view (Issue #1640) +* Instruct browsers to prefetch newest post when visiting the front page +* Add a ``sort`` parameter to the post-list directive to sort posts in + the list using natsort. (Issue #1635) + +Bugfixes +-------- + +* Make ``.islink`` work properly (via Issue #1536) +* RSS_LINKS_APPEND_QUERY not working in RSS feeds for tags +* `nikola check -l` didn’t scan posts +* Don’t use sets for ``FAVICONS`` (Issue #1674) +* Posts/Pages that use post-list will never be up to date (Issue #1671) +* Support using post.text() in post_list_directive.tmpl (Issue #1671) +* Avoid recursive dep when using post-list in a post (Issue #1671) +* Encode IDNs to Punycode in ``nikola init`` and in links; + show an error if the site URL is not Punycode (Issue #1644) +* Make ``images`` the default output directory for IMAGE_FOLDERS + (Issue #1663) +* Don't default to any swatch in bootswatch_theme (Issue #1656) +* Fix ``nikola check -l`` for absolute and full-path URL styles + (Issue #1650) +* Really add missing trailing slashes in ``BASE_URL`` (Issue #1651) +* Check if files exists before adding them as post-list dependencies + (Issue #1646) +* Fix build command in ``nikola auto`` (Issue #1641) +* Update Bootstrap to v3.3.4 +* Update jquery-colorbox +* Fix symlinks for moment.js in Windows +* Fix code.css bundling in Windows +* Listings in posts now work in Windows (Issue #1631) +* Add 20 seconds to reading time per embedded media + +New in v7.3.1.1 +=============== + +* Emergency release to pin doit version to 0.27.0 +* No code changes since v7.3.1 (not even ``nikola --version``) + +New in v7.3.1 +============= + +Features +-------- + +* Separate new option IMAGE_THUMBNAIL_SIZE for setting size of + thumbnails created by scale_images plugin (Issue #1606) +* Don't create larger thumbnails for panorama images in scale_images + (Issue #1606) +* Added ``root`` path handler (via Issues #1008, #1573) +* Added RSS feeds to gallery HEAD (part of Issue #786) + +Bugfixes +-------- + +* Use pyphen properly when there are no dictionaries for this language + (Issue #1613) +* Fix ``nikola deploy`` when there is no cache (Issue #1615) +* Report issues in scale_images properly (Issue #1598) +* Correctly read sub-timezones in ``nikola init`` (via Issue #1599) +* Fix zoneinfo reading in ``nikola init`` (Issue #1599) +* Fix ``.islink`` detection for galleries (via Issue #1536) +* Links to languages point to site root and not the blog (Issue #1008) +* Brand link is now language-specific (Issue #1573) +* Fixed compatibility with IPython 3.x (Issue #1581) +* Compilers mark tasks as out of date if compiler-specific options and + plugins change (Issue #1523) + +New in v7.3.0 +============= + +Features +-------- + +* Added possibility for plugins to define how to read metadata from files +* Added ``-a``, ``--author`` option to set post author field +* Added option INDEXES_PRETTY_PAGE_URL to make URLs for indexes + pages more pretty. (Issue #1548) +* Added ``-i``, ``--import`` argument to ``new_post`` for importing + existing post contents (Issue #1385) +* Added warning about ``password`` in posts being insecure + (Issue #1547) +* INDEXES_TITLE and INDEXES_PAGES are translatable (Issue #1544) +* Added new option ARCHIVES_ARE_INDEXES which allows archive pages + which list posts to be rendered with the post contents. + (Issue #1537) +* Added new option INDEXES_STATIC which allows to define the + page ordering for indexes (Issue #1537). Also, if tag pages are + created as indexes, they will behave more close to the + default indexes. +* Use ``table`` line-numbering style with reST code, making + copy-pasting code possible (Issue #1285) +* Tag and category pages are now more separated. The prefix for + category pages can be changed and the folder can be modified + independently of the tags' folder. (Issue #1535) +* Writing the tag cloud data file can now be disabled. Will be + disabled by default in the future. (Issue #1535) +* The ``utils.config_changed`` function now takes an optional extra + argument, ``identifier``, used to identify the source of a specific + dependency save. As such, ALL your files will be rebuilt after + upgrading. (Issue #1526 via #1521) +* New option GALLERY_FOLDERS replacing GALLERY_PATH (Issue #1511) +* New PANDOC_OPTIONS option (Issue #1492) +* New tab-width option in code-block directive (Issue #1514) +* New option TAG_PAGES_DESCRIPTIONS for optionally making individual + tag pages more unique and interesting (Issue #1486) +* New option LISTINGS_FOLDERS (which replaces LISTINGS_FOLDER) which + allows to separate input and output folder names for listings, and + allows to have more than one listings folder (Issue #1499) +* ReST listing directive now honors alternative listings folder names + (Issue #1499) +* New command line option --conf= to specify the configuration file + (default is conf.py) (Issue #1501) +* Added Arabic translation (by darkwise) +* Added Danish translation (by mikkelkristiansen) +* Added Indonesian translation (by Willy Sudiarto Raharjo) +* Added Korean translation (by Dong Geun) +* Added Serbian translation (by Ivan Radeljic) +* Added Swedish translation (by Johan Sommerfeld) +* New advanced option RSS_LINKS_APPEND_QUERY for tracking traffic + from RSS subscribers +* Add ``robots`` meta tag with value ``noindex`` for drafts + (Issue #1489) +* New option TAGLIST_MINIMUM_POSTS allows hiding unpopular tags from + the tag index page (Issue #1484) +* New options CREATE_FULL_ARCHIVES and CREATE_DAILY_ARCHIVE which + allow to create non-hierarchical archives and archives for days, + respectively (Issue #1494) +* New plugin for creating image thumbnails, and a corresponding reST + plugin (Issue #1527) + +Bugfixes +-------- + +* Handle over-and-under-lined titles in rst for guessing title (Issue #1539) +* Don't apply colorbox to figures if they are of islink class. (Issue #1536) +* Turned minify_lines into a no-op (Issue #1497) +* Don’t classify unpublished posts as pages (Issue #1577) +* Fixed a ``TranslatableSetting.langformat`` race condition +* Fixed ``TranslatableSetting`` instantiation in + ``TranslatableSetting.langformat`` (Issue #1571) +* Fixed ``rss.xsl`` path for blogs not deployed to server root + (Issue #1563) +* Respect SHOW_UNTRANSLATED_POSTS = False in archives + and for untranslated source files (Issue #1360) +* Make sure drafts don’t appear in sitemaps with multiple languages + (Issue #1489) +* Make site.posts_per_file cover all languages (Issues #1270, #1489) +* Fix ANNOTATIONS not working at all (Issue #1477) +* Fix asking questions with Unicode chars in Python 2 (Issue #1476) +* Use ADDITIONAL_METADATA with the two-file format (Issue #1471) +* Make previewimage compatible with sites deployed to subdirectories + (Issue #1473) +* Make sitemaps work on sites deployed to subdirectories + (Issue #1472) + +New in v7.2.0 +============= + +Features +-------- + +* Added support for fancy dates via moment.js (Issue #1256) +* Updates: jQuery v1.11.1, Bootstrap v3.3.0 +* Allow presets usage with ``nikola deploy`` — ``DEPLOY_COMMANDS`` is + now a dict of {preset: commands} (Issue #1452) +* New ``GLOBAL_CONTEXT_FILLER`` setting, functions listed there will + be called with the local context and the template name before + template rendering. (Issue #1451) +* New ``USE_CDN_WARNING`` setting to block warnings about potential + ``USE_CDN`` misuse (defaults to True) +* ``nikola check -l`` will warn about mixed-security (HTTP on HTTPS) +* New ``ConfigPlugin`` category (without any specific behavior by default) +* New meta property “previewimage” for use with Open Graph (Issue #1421) +* Expose publishing date, tags, and more in Open Graph +* XSL Transform RSS into pretty and helpful webpages when opened in browsers (Issue #1411) + +Bugfixes +-------- + +* Don’t pull by default in ``github_deploy`` (Issue #1464) +* disabled hyphenation for paragraphs with inline math (Issue #1461) +* Support filters for all tasks (Issue #1459) +* Don’t check cache/ in ``nikola check -l`` (Issue #1447) +* Fix new_post for pandoc format (Issue #1445) +* Fix STORY_INDEX generation (Issue #1444) +* Fix bootswatch creation version check (Issue #1441) +* Never rebase while pulling in ``github_deploy`` +* Handle better ``new_post --format=pandoc`` when pandoc is not defined (Issue #1422) +* Open Graph properly uses latest RDFa in HTML – fixes validation +* Fix sitemap generation (Issue #1397 via #1032) +* Use destination folder names as titles for titleless listings +* Fixed problems with installation from .tar.gz under Windows (Issue #1417) +* Fixed encoding problems in WordPress urlmap writer (Issue #1416) +* Added back atom:link in RSS feeds +* Fixed Nikola-based page redirects in Python 2 (Issue #1414) +* Fixed files/\*.php (skip post/story-specific filters) (Issue #1403) +* Warn about missing / in BASE_URL differently (explicit request to + fix the config file) +* Fix broken ``auto -b`` option (Issue #1437) + New in v7.1.0 ============= @@ -610,7 +946,7 @@ Bugfixes * Added .rst to the default reStructuredText extensions (via Issue #542) * Moved the sample site to the new one-file format (Issue #542) * Escape HTML in titles (Issue #537) -* Fixed issues with index pages indices (Issue #532) +* Fixed issues with index pages indexes (Issue #532) * Fixed IPython plugin to work with the latest IPython.nbconvert machinery * Fixed failing build because of hidden folders and files inside post folder diff --git a/LICENSE.txt b/LICENSE.txt index a57a89a..d746cfc 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright © 2012-2014 Roberto Alsina and others. +Copyright © 2012-2015 Roberto Alsina and others. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -33,23 +33,29 @@ It has many features, but here are some of the nicer ones: * `Blogs, with tags, feeds, archives, comments, etc.`__ * `Themable`_ * Fast builds, thanks to `doit`_ -* Flexible, extensible via plugins +* Flexible, extensible via the dozens of `available plugins`_ * Small codebase (programmers can understand all of Nikola core in a day) * `reStructuredText`_ or Markdown as input language (also Wiki, BBCode, Textile, and HTML) * Easy `image galleries`_ (just drop files in a folder!) * Syntax highlighting for almost any programming language or markup * Multilingual sites, `translated to 18 languages.`__ * Doesn't reinvent wheels, leverages existing tools. -* Python 2.6, 2.7, 3.3 and 3.4 compatible. +* Python 2.7, 3.3 and 3.4 compatible. -.. _Nikola Handbook: http://getnikola.com/handbook.html#why-static -__ http://users.getnikola.com/ -.. _Themable: http://themes.getnikola.com +.. _Nikola Handbook: https://getnikola.com/handbook.html#why-static +__ https://users.getnikola.com/ +.. _Themable: https://themes.getnikola.com .. _doit: http://pydoit.org -.. _reStructuredText: http://getnikola.com/quickstart.html -.. _image galleries: http://getnikola.com/galleries/demo/ +.. _available plugins: https://plugins.getnikola.com/ +.. _reStructuredText: https://getnikola.com/quickstart.html +.. _image galleries: https://getnikola.com/galleries/demo/ __ https://www.transifex.com/projects/p/nikola/ +Nikola Architecture +------------------- + +.. image:: https://getnikola.com/images/architecture.png + Installation Instructions ------------------------- @@ -65,4 +71,4 @@ For tests (see tests/README.rst for more details):: pip install Nikola[extras,tests] -For more information, see http://getnikola.com/ +For more information, see https://getnikola.com/ diff --git a/appveyor.yml b/appveyor.yml index e57cd4a..d4cd55c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -2,26 +2,18 @@ build: false environment: matrix: - #- PYTHON: "C:/Python34" - PYTHON: "C:/Python27" + #- PYTHON: "C:/Python34" init: - "ECHO %PYTHON%" - ps: "ls C:/Python*" install: - ps: (new-object net.webclient).DownloadFile('https://raw.github.com/pypa/pip/master/contrib/get-pip.py', 'C:/get-pip.py') - "%PYTHON%/python.exe C:/get-pip.py" - - ps: (new-object net.webclient).DownloadFile('https://pypi.python.org/packages/2.7/l/lxml/lxml-3.3.5.win32-py2.7.exe', 'C:/Python27/get-lxml.exe') - #- ps: (new-object net.webclient).DownloadFile('http://www.lfd.uci.edu/~gohlke/pythonlibs/5hgp4h3m/lxml-3.3.5.win32-py3.4.exe', 'C:/Python34/get-lxml.exe') - - "%PYTHON%/Scripts/easy_install.exe %PYTHON%/get-lxml.exe" -# can't install coverage etc. + - "%PYTHON%/Scripts/pip.exe install --upgrade setuptools" - "%PYTHON%/Scripts/pip.exe install -r requirements-extras.txt pytest mock freezegun" -# temporary change, install with setup.py install so symlinks are expanned -# - "%PYTHON%/Scripts/pip.exe install ." - "%PYTHON%/python.exe setup.py install" - # temp workaround - - "%PYTHON%/Scripts/pip.exe uninstall -y webassets" - test_script: - "set path=%PYTHON%/Scripts;%path%" - "%PYTHON%/python.exe --version" @@ -9,8 +9,10 @@ "license": "MIT", "private": true, "dependencies": { - "bootstrap": "~3.2.0", + "bootstrap": "~3.3.4", "jquery": "<2.0.0", - "jquery-colorbox": "~1.5.10" + "jquery-colorbox": "~1.6.0", + "moment": "~2.10.3", + "livereload-js": "~2.2.1" } } diff --git a/bower_components/bootstrap/.bower.json b/bower_components/bootstrap/.bower.json index 4325ed9..7fde9e3 100644 --- a/bower_components/bootstrap/.bower.json +++ b/bower_components/bootstrap/.bower.json @@ -1,7 +1,6 @@ { "name": "bootstrap", "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", - "version": "3.2.0", "keywords": [ "css", "js", @@ -13,17 +12,14 @@ "web" ], "homepage": "http://getbootstrap.com", + "license": "MIT", + "moduleType": "globals", "main": [ "less/bootstrap.less", - "dist/css/bootstrap.css", - "dist/js/bootstrap.js", - "dist/fonts/glyphicons-halflings-regular.eot", - "dist/fonts/glyphicons-halflings-regular.svg", - "dist/fonts/glyphicons-halflings-regular.ttf", - "dist/fonts/glyphicons-halflings-regular.woff" + "dist/js/bootstrap.js" ], "ignore": [ - ".*", + "/.*", "_config.yml", "CNAME", "composer.json", @@ -33,16 +29,16 @@ "test-infra" ], "dependencies": { - "jquery": ">= 1.9.0" + "jquery": ">= 1.9.1" }, - "_release": "3.2.0", + "version": "3.3.5", + "_release": "3.3.5", "_resolution": { "type": "version", - "tag": "v3.2.0", - "commit": "c068162161154a4b85110ea1e7dd3d7897ce2b72" + "tag": "v3.3.5", + "commit": "16b48259a62f576e52c903c476bd42b90ab22482" }, "_source": "git://github.com/twbs/bootstrap.git", - "_target": "~3.2.0", - "_originalSource": "bootstrap", - "_direct": true + "_target": "~3.3.4", + "_originalSource": "bootstrap" }
\ No newline at end of file diff --git a/bower_components/bootstrap/Gruntfile.js b/bower_components/bootstrap/Gruntfile.js index 66e1de3..4c021ce 100644 --- a/bower_components/bootstrap/Gruntfile.js +++ b/bower_components/bootstrap/Gruntfile.js @@ -1,7 +1,7 @@ /*! * Bootstrap's Gruntfile * http://getbootstrap.com - * Copyright 2013-2014 Twitter, Inc. + * Copyright 2013-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ @@ -20,7 +20,21 @@ module.exports = function (grunt) { var npmShrinkwrap = require('npm-shrinkwrap'); var generateGlyphiconsData = require('./grunt/bs-glyphicons-data-generator.js'); var BsLessdocParser = require('./grunt/bs-lessdoc-parser.js'); + var getLessVarsData = function () { + var filePath = path.join(__dirname, 'less/variables.less'); + var fileContent = fs.readFileSync(filePath, { encoding: 'utf8' }); + var parser = new BsLessdocParser(fileContent); + return { sections: parser.parseFile() }; + }; var generateRawFiles = require('./grunt/bs-raw-files-generator.js'); + var generateCommonJSModule = require('./grunt/bs-commonjs-generator.js'); + var configBridge = grunt.file.readJSON('./grunt/configBridge.json', { encoding: 'utf8' }); + + Object.keys(configBridge.paths).forEach(function (key) { + configBridge.paths[key].forEach(function (val, i, arr) { + arr[i] = path.join('./docs/assets', val); + }); + }); // Project configuration. grunt.initConfig({ @@ -30,14 +44,15 @@ module.exports = function (grunt) { banner: '/*!\n' + ' * Bootstrap v<%= pkg.version %> (<%= pkg.homepage %>)\n' + ' * Copyright 2011-<%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' + - ' * Licensed under <%= pkg.license.type %> (<%= pkg.license.url %>)\n' + + ' * Licensed under the <%= pkg.license %> license\n' + ' */\n', - // NOTE: This jqueryCheck code is duplicated in customizer.js; if making changes here, be sure to update the other copy too. - jqueryCheck: 'if (typeof jQuery === \'undefined\') { throw new Error(\'Bootstrap\\\'s JavaScript requires jQuery\') }\n\n', + jqueryCheck: configBridge.config.jqueryCheck.join('\n'), + jqueryVersionCheck: configBridge.config.jqueryVersionCheck.join('\n'), // Task configuration. clean: { - dist: ['dist', 'docs/dist'] + dist: 'dist', + docs: 'docs/dist' }, jshint: { @@ -48,9 +63,9 @@ module.exports = function (grunt) { options: { jshintrc: 'grunt/.jshintrc' }, - src: ['Gruntfile.js', 'grunt/*.js'] + src: ['Gruntfile.js', 'package.js', 'grunt/*.js'] }, - src: { + core: { src: 'js/*.js' }, test: { @@ -60,7 +75,7 @@ module.exports = function (grunt) { src: 'js/tests/unit/*.js' }, assets: { - src: ['docs/assets/js/_src/*.js', 'docs/assets/js/*.js', '!docs/assets/js/*.min.js'] + src: ['docs/assets/js/src/*.js', 'docs/assets/js/*.js', '!docs/assets/js/*.min.js'] } }, @@ -71,8 +86,8 @@ module.exports = function (grunt) { grunt: { src: '<%= jshint.grunt.src %>' }, - src: { - src: '<%= jshint.src.src %>' + core: { + src: '<%= jshint.core.src %>' }, test: { src: '<%= jshint.test.src %>' @@ -87,7 +102,7 @@ module.exports = function (grunt) { concat: { options: { - banner: '<%= banner %>\n<%= jqueryCheck %>', + banner: '<%= banner %>\n<%= jqueryCheck %>\n<%= jqueryVersionCheck %>', stripBanners: false }, bootstrap: { @@ -111,30 +126,22 @@ module.exports = function (grunt) { uglify: { options: { + compress: { + warnings: false + }, + mangle: true, preserveComments: 'some' }, - bootstrap: { + core: { src: '<%= concat.bootstrap.dest %>', dest: 'dist/js/<%= pkg.name %>.min.js' }, customize: { - src: [ - 'docs/assets/js/_vendor/less.min.js', - 'docs/assets/js/_vendor/jszip.min.js', - 'docs/assets/js/_vendor/uglify.min.js', - 'docs/assets/js/_vendor/blob.js', - 'docs/assets/js/_vendor/filesaver.js', - 'docs/assets/js/raw-files.min.js', - 'docs/assets/js/_src/customizer.js' - ], + src: configBridge.paths.customizerJs, dest: 'docs/assets/js/customize.min.js' }, docsJs: { - src: [ - 'docs/assets/js/_vendor/holder.js', - 'docs/assets/js/_vendor/ZeroClipboard.min.js', - 'docs/assets/js/_src/application.js' - ], + src: configBridge.paths.docsJs, dest: 'docs/assets/js/docs.min.js' } }, @@ -155,9 +162,8 @@ module.exports = function (grunt) { sourceMapURL: '<%= pkg.name %>.css.map', sourceMapFilename: 'dist/css/<%= pkg.name %>.css.map' }, - files: { - 'dist/css/<%= pkg.name %>.css': 'less/bootstrap.less' - } + src: 'less/bootstrap.less', + dest: 'dist/css/<%= pkg.name %>.css' }, compileTheme: { options: { @@ -167,24 +173,14 @@ module.exports = function (grunt) { sourceMapURL: '<%= pkg.name %>-theme.css.map', sourceMapFilename: 'dist/css/<%= pkg.name %>-theme.css.map' }, - files: { - 'dist/css/<%= pkg.name %>-theme.css': 'less/theme.less' - } + src: 'less/theme.less', + dest: 'dist/css/<%= pkg.name %>-theme.css' } }, autoprefixer: { options: { - browsers: [ - 'Android 2.3', - 'Android >= 4', - 'Chrome >= 20', - 'Firefox >= 24', // Firefox 24 is the latest ESR - 'Explorer >= 8', - 'iOS >= 6', - 'Opera >= 12', - 'Safari >= 6' - ] + browsers: configBridge.config.autoprefixerBrowsers }, core: { options: { @@ -199,7 +195,7 @@ module.exports = function (grunt) { src: 'dist/css/<%= pkg.name %>-theme.css' }, docs: { - src: 'docs/assets/css/_src/docs.css' + src: ['docs/assets/css/src/docs.css'] }, examples: { expand: true, @@ -213,7 +209,7 @@ module.exports = function (grunt) { options: { csslintrc: 'less/.csslintrc' }, - src: [ + dist: [ 'dist/css/bootstrap.css', 'dist/css/bootstrap-theme.css' ], @@ -225,41 +221,35 @@ module.exports = function (grunt) { ids: false, 'overqualified-elements': false }, - src: 'docs/assets/css/_src/docs.css' + src: 'docs/assets/css/src/docs.css' } }, cssmin: { options: { + // TODO: disable `zeroUnits` optimization once clean-css 3.2 is released + // and then simplify the fix for https://github.com/twbs/bootstrap/issues/14837 accordingly compatibility: 'ie8', keepSpecialComments: '*', - noAdvanced: true + advanced: false }, - core: { - files: { - 'dist/css/<%= pkg.name %>.min.css': 'dist/css/<%= pkg.name %>.css', - 'dist/css/<%= pkg.name %>-theme.min.css': 'dist/css/<%= pkg.name %>-theme.css' - } + minifyCore: { + src: 'dist/css/<%= pkg.name %>.css', + dest: 'dist/css/<%= pkg.name %>.min.css' + }, + minifyTheme: { + src: 'dist/css/<%= pkg.name %>-theme.css', + dest: 'dist/css/<%= pkg.name %>-theme.min.css' }, docs: { src: [ - 'docs/assets/css/_src/docs.css', - 'docs/assets/css/_src/pygments-manni.css' + 'docs/assets/css/src/pygments-manni.css', + 'docs/assets/css/src/docs.css' ], dest: 'docs/assets/css/docs.min.css' } }, - usebanner: { - options: { - position: 'top', - banner: '<%= banner %>' - }, - files: { - src: 'dist/css/*.css' - } - }, - csscomb: { options: { config: 'less/.csscomb.json' @@ -277,9 +267,8 @@ module.exports = function (grunt) { dest: 'docs/examples/' }, docs: { - files: { - 'docs/assets/css/_src/docs.css': 'docs/assets/css/_src/docs.css' - } + src: 'docs/assets/css/src/docs.css', + dest: 'docs/assets/css/src/docs.css' } }, @@ -291,13 +280,11 @@ module.exports = function (grunt) { }, docs: { expand: true, - cwd: './dist', + cwd: 'dist/', src: [ - '{css,js}/*.min.*', - 'css/*.map', - 'fonts/*' + '**/*' ], - dest: 'docs/dist' + dest: 'docs/dist/' } }, @@ -311,54 +298,74 @@ module.exports = function (grunt) { }, jekyll: { - docs: {} + options: { + config: '_config.yml' + }, + docs: {}, + github: { + options: { + raw: 'github: true' + } + } }, - jade: { - compile: { + htmlmin: { + dist: { options: { - pretty: true, - data: function () { - var filePath = path.join(__dirname, 'less/variables.less'); - var fileContent = fs.readFileSync(filePath, { encoding: 'utf8' }); - var parser = new BsLessdocParser(fileContent); - return { sections: parser.parseFile() }; - } + collapseWhitespace: true, + conservativeCollapse: true, + minifyCSS: true, + minifyJS: true, + removeAttributeQuotes: true, + removeComments: true }, - files: { - 'docs/_includes/customizer-variables.html': 'docs/_jade/customizer-variables.jade', - 'docs/_includes/nav/customize.html': 'docs/_jade/customizer-nav.jade' - } + expand: true, + cwd: '_gh_pages', + dest: '_gh_pages', + src: [ + '**/*.html', + '!examples/**/*.html' + ] } }, - validation: { + jade: { options: { - charset: 'utf-8', - doctype: 'HTML5', - failHard: true, - reset: true, - relaxerror: [ - 'Bad value X-UA-Compatible for attribute http-equiv on element meta.', - 'Element img is missing required attribute src.' - ] + pretty: true, + data: getLessVarsData }, - files: { - src: '_gh_pages/**/*.html' + customizerVars: { + src: 'docs/_jade/customizer-variables.jade', + dest: 'docs/_includes/customizer-variables.html' + }, + customizerNav: { + src: 'docs/_jade/customizer-nav.jade', + dest: 'docs/_includes/nav/customize.html' } }, + htmllint: { + options: { + ignore: [ + 'Attribute "autocomplete" not allowed on element "button" at this point.', + 'Attribute "autocomplete" not allowed on element "input" at this point.', + 'Element "img" is missing required attribute "src".' + ] + }, + src: '_gh_pages/**/*.html' + }, + watch: { src: { - files: '<%= jshint.src.src %>', - tasks: ['jshint:src', 'qunit'] + files: '<%= jshint.core.src %>', + tasks: ['jshint:core', 'qunit', 'concat'] }, test: { files: '<%= jshint.test.src %>', tasks: ['jshint:test', 'qunit'] }, less: { - files: 'less/*.less', + files: 'less/**/*.less', tasks: 'less' } }, @@ -370,6 +377,14 @@ module.exports = function (grunt) { return old ? RegExp.quote(old) : old; })(), replacement: grunt.option('newver'), + exclude: [ + 'dist/fonts', + 'docs/assets', + 'fonts', + 'js/tests/vendor', + 'node_modules', + 'test-infra' + ], recursive: true } }, @@ -378,9 +393,10 @@ module.exports = function (grunt) { all: { options: { build: process.env.TRAVIS_JOB_ID, - concurrency: 10, + throttled: 10, maxRetries: 3, - urls: ['http://127.0.0.1:3000/js/tests/index.html'], + maxPollRetries: 4, + urls: ['http://127.0.0.1:3000/js/tests/index.html?hidepassed'], browsers: grunt.file.readYAML('grunt/sauce_browsers.yml') } } @@ -390,7 +406,27 @@ module.exports = function (grunt) { npmUpdate: { command: 'npm update' } + }, + + compress: { + main: { + options: { + archive: 'bootstrap-<%= pkg.version %>-dist.zip', + mode: 'zip', + level: 9, + pretty: true + }, + files: [ + { + expand: true, + cwd: 'dist/', + src: ['**'], + dest: 'bootstrap-<%= pkg.version %>-dist' + } + ] + } } + }); @@ -399,7 +435,7 @@ module.exports = function (grunt) { require('time-grunt')(grunt); // Docs HTML validation task - grunt.registerTask('validate-html', ['jekyll', 'validation']); + grunt.registerTask('validate-html', ['jekyll:docs', 'htmllint']); var runSubset = function (subset) { return !process.env.TWBS_TEST || process.env.TWBS_TEST === subset; @@ -411,8 +447,10 @@ module.exports = function (grunt) { // Test task. var testSubtasks = []; // Skip core tests if running a different subset of the test suite - if (runSubset('core')) { - testSubtasks = testSubtasks.concat(['dist-css', 'csslint', 'jshint', 'jscs', 'qunit', 'build-customizer-html']); + if (runSubset('core') && + // Skip core tests if this is a Savage build + process.env.TRAVIS_REPO_SLUG !== 'twbs-savage/bootstrap') { + testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'csslint:dist', 'test-js', 'docs']); } // Skip HTML validation if running a different subset of the test suite if (runSubset('validate-html') && @@ -430,22 +468,20 @@ module.exports = function (grunt) { testSubtasks.push('saucelabs-qunit'); } grunt.registerTask('test', testSubtasks); + grunt.registerTask('test-js', ['jshint:core', 'jshint:test', 'jshint:grunt', 'jscs:core', 'jscs:test', 'jscs:grunt', 'qunit']); // JS distribution task. - grunt.registerTask('dist-js', ['concat', 'uglify']); + grunt.registerTask('dist-js', ['concat', 'uglify:core', 'commonjs']); // CSS distribution task. grunt.registerTask('less-compile', ['less:compileCore', 'less:compileTheme']); - grunt.registerTask('dist-css', ['less-compile', 'autoprefixer', 'usebanner', 'csscomb', 'cssmin']); - - // Docs distribution task. - grunt.registerTask('dist-docs', 'copy:docs'); + grunt.registerTask('dist-css', ['less-compile', 'autoprefixer:core', 'autoprefixer:theme', 'csscomb:dist', 'cssmin:minifyCore', 'cssmin:minifyTheme']); // Full distribution task. - grunt.registerTask('dist', ['clean', 'dist-css', 'copy:fonts', 'dist-js', 'dist-docs']); + grunt.registerTask('dist', ['clean:dist', 'dist-css', 'copy:fonts', 'dist-js']); // Default task. - grunt.registerTask('default', ['test', 'dist', 'build-glyphicons-data', 'build-customizer']); + grunt.registerTask('default', ['clean:dist', 'copy:fonts', 'test']); // Version numbering task. // grunt change-version-number --oldver=A.B.C --newver=X.Y.Z @@ -462,6 +498,21 @@ module.exports = function (grunt) { generateRawFiles(grunt, banner); }); + grunt.registerTask('commonjs', 'Generate CommonJS entrypoint module in dist dir.', function () { + var srcFiles = grunt.config.get('concat.bootstrap.src'); + var destFilepath = 'dist/js/npm.js'; + generateCommonJSModule(grunt, srcFiles, destFilepath); + }); + + // Docs task. + grunt.registerTask('docs-css', ['autoprefixer:docs', 'autoprefixer:examples', 'csscomb:docs', 'csscomb:examples', 'cssmin:docs']); + grunt.registerTask('lint-docs-css', ['csslint:docs', 'csslint:examples']); + grunt.registerTask('docs-js', ['uglify:docsJs', 'uglify:customize']); + grunt.registerTask('lint-docs-js', ['jshint:assets', 'jscs:assets']); + grunt.registerTask('docs', ['docs-css', 'lint-docs-css', 'docs-js', 'lint-docs-js', 'clean:docs', 'copy:docs', 'build-glyphicons-data', 'build-customizer']); + + grunt.registerTask('prep-release', ['dist', 'docs', 'jekyll:github', 'htmlmin', 'compress']); + // Task for updating the cached npm packages used by the Travis build (which are controlled by test-infra/npm-shrinkwrap.json). // This task should be run and the updated file should be committed whenever Bootstrap's dependencies change. grunt.registerTask('update-shrinkwrap', ['exec:npmUpdate', '_update-shrinkwrap']); @@ -469,7 +520,7 @@ module.exports = function (grunt) { var done = this.async(); npmShrinkwrap({ dev: true, dirname: __dirname }, function (err) { if (err) { - grunt.fail.warn(err) + grunt.fail.warn(err); } var dest = 'test-infra/npm-shrinkwrap.json'; fs.renameSync('npm-shrinkwrap.json', dest); diff --git a/bower_components/bootstrap/LICENSE b/bower_components/bootstrap/LICENSE index 8d94aa9..f4c52d6 100644 --- a/bower_components/bootstrap/LICENSE +++ b/bower_components/bootstrap/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2011-2014 Twitter, Inc +Copyright (c) 2011-2015 Twitter, Inc Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/bower_components/bootstrap/README.md b/bower_components/bootstrap/README.md index 82c4a17..34c8b5a 100644 --- a/bower_components/bootstrap/README.md +++ b/bower_components/bootstrap/README.md @@ -1,32 +1,36 @@ # [Bootstrap](http://getbootstrap.com) -[](http://badge.fury.io/bo/bootstrap) -[](http://badge.fury.io/js/bootstrap) -[](http://travis-ci.org/twbs/bootstrap) -[](https://david-dm.org/twbs/bootstrap#info=devDependencies) +[](https://bootstrap-slack.herokuapp.com) + +[](https://www.npmjs.com/package/bootstrap) +[](https://travis-ci.org/twbs/bootstrap) +[](https://david-dm.org/twbs/bootstrap#info=devDependencies) [](https://saucelabs.com/u/bootstrap) -Bootstrap is a sleek, intuitive, and powerful front-end framework for faster and easier web development, created by [Mark Otto](http://twitter.com/mdo) and [Jacob Thornton](http://twitter.com/fat), and maintained by the [core team](https://github.com/twbs?tab=members) with the massive support and involvement of the community. +Bootstrap is a sleek, intuitive, and powerful front-end framework for faster and easier web development, created by [Mark Otto](https://twitter.com/mdo) and [Jacob Thornton](https://twitter.com/fat), and maintained by the [core team](https://github.com/orgs/twbs/people) with the massive support and involvement of the community. To get started, check out <http://getbootstrap.com>! ## Table of contents - - [Quick start](#quick-start) - - [Bugs and feature requests](#bugs-and-feature-requests) - - [Documentation](#documentation) - - [Contributing](#contributing) - - [Community](#community) - - [Versioning](#versioning) - - [Creators](#creators) - - [Copyright and license](#copyright-and-license) +- [Quick start](#quick-start) +- [Bugs and feature requests](#bugs-and-feature-requests) +- [Documentation](#documentation) +- [Contributing](#contributing) +- [Community](#community) +- [Versioning](#versioning) +- [Creators](#creators) +- [Copyright and license](#copyright-and-license) ## Quick start -Three quick start options are available: +Several quick start options are available: -- [Download the latest release](https://github.com/twbs/bootstrap/archive/v3.2.0.zip). +- [Download the latest release](https://github.com/twbs/bootstrap/archive/v3.3.5.zip). - Clone the repo: `git clone https://github.com/twbs/bootstrap.git`. - Install with [Bower](http://bower.io): `bower install bootstrap`. +- Install with [npm](https://www.npmjs.com): `npm install bootstrap`. +- Install with [Meteor](https://www.meteor.com): `meteor add twbs:bootstrap`. +- Install with [Composer](https://getcomposer.org): `composer require twbs/bootstrap`. Read the [Getting started page](http://getbootstrap.com/getting-started/) for information on the framework contents, templates and examples, and more. @@ -38,8 +42,10 @@ Within the download you'll find the following directories and files, logically g bootstrap/ ├── css/ │ ├── bootstrap.css +│ ├── bootstrap.css.map │ ├── bootstrap.min.css │ ├── bootstrap-theme.css +│ ├── bootstrap-theme.css.map │ └── bootstrap-theme.min.css ├── js/ │ ├── bootstrap.js @@ -48,10 +54,11 @@ bootstrap/ ├── glyphicons-halflings-regular.eot ├── glyphicons-halflings-regular.svg ├── glyphicons-halflings-regular.ttf - └── glyphicons-halflings-regular.woff + ├── glyphicons-halflings-regular.woff + └── glyphicons-halflings-regular.woff2 ``` -We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). Fonts from Glyphicons are included, as is the optional Bootstrap theme. +We provide compiled CSS and JS (`bootstrap.*`), as well as compiled and minified CSS and JS (`bootstrap.min.*`). CSS [source maps](https://developer.chrome.com/devtools/docs/css-preprocessors) (`bootstrap.*.map`) are available for use with certain browsers' developer tools. Fonts from Glyphicons are included, as is the optional Bootstrap theme. @@ -66,10 +73,11 @@ Bootstrap's documentation, included in this repo in the root directory, is built ### Running documentation locally -1. If necessary, [install Jekyll](http://jekyllrb.com/docs/installation) (requires v2.0.x). - - **Windows users:** Read [this unofficial guide](https://github.com/juthilo/run-jekyll-on-windows/) to get Jekyll up and running without problems. We use Pygments for syntax highlighting, so make sure to read the sections on installing Python and Pygments. -2. From the root `/bootstrap` directory, run `jekyll serve` in the command line. -3. Open <http://localhost:9001> in your browser, and voilà. +1. If necessary, [install Jekyll](http://jekyllrb.com/docs/installation) (requires v2.5.x). + - **Windows users:** Read [this unofficial guide](http://jekyll-windows.juthilo.com/) to get Jekyll up and running without problems. +2. Install the Ruby-based syntax highlighter, [Rouge](https://github.com/jneen/rouge), with `gem install rouge`. +3. From the root `/bootstrap` directory, run `jekyll serve` in the command line. +4. Open <http://localhost:9001> in your browser, and voilà. Learn more about using Jekyll by reading its [documentation](http://jekyllrb.com/docs/home/). @@ -85,7 +93,7 @@ Documentation for v2.3.2 has been made available for the time being at <http://g Please read through our [contributing guidelines](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md). Included are directions for opening issues, coding standards, and notes on development. -Moreover, if your pull request contains JavaScript patches or features, you must include relevant unit tests. All HTML and CSS should conform to the [Code Guide](http://github.com/mdo/code-guide), maintained by [Mark Otto](http://github.com/mdo). +Moreover, if your pull request contains JavaScript patches or features, you must include [relevant unit tests](https://github.com/twbs/bootstrap/tree/master/js/tests). All HTML and CSS should conform to the [Code Guide](https://github.com/mdo/code-guide), maintained by [Mark Otto](https://github.com/mdo). Editor preferences are available in the [editor config](https://github.com/twbs/bootstrap/blob/master/.editorconfig) for easy use in common text editors. Read more and download plugins at <http://editorconfig.org>. @@ -93,12 +101,14 @@ Editor preferences are available in the [editor config](https://github.com/twbs/ ## Community -Keep track of development and community news. +Get updates on Bootstrap's development and chat with the project maintainers and community members. -- Follow [@twbootstrap on Twitter](http://twitter.com/twbootstrap). +- Follow [@getbootstrap on Twitter](https://twitter.com/getbootstrap). - Read and subscribe to [The Official Bootstrap Blog](http://blog.getbootstrap.com). -- Chat with fellow Bootstrappers in IRC. On the `irc.freenode.net` server, in the `##twitter-bootstrap` channel. -- Implementation help may be found at Stack Overflow (tagged [`twitter-bootstrap-3`](http://stackoverflow.com/questions/tagged/twitter-bootstrap-3)). +- Join [the official Slack room](https://bootstrap-slack.herokuapp.com). +- Chat with fellow Bootstrappers in IRC. On the `irc.freenode.net` server, in the `##bootstrap` channel. +- Implementation help may be found at Stack Overflow (tagged [`twitter-bootstrap-3`](https://stackoverflow.com/questions/tagged/twitter-bootstrap-3)). +- Developers should use the keyword `bootstrap` on packages which modify or add to the functionality of Bootstrap when distributing through [npm](https://www.npmjs.com/browse/keyword/bootstrap) or similar delivery mechanisms for maximum discoverability. @@ -112,16 +122,16 @@ For transparency into our release cycle and in striving to maintain backward com **Mark Otto** -- <http://twitter.com/mdo> -- <http://github.com/mdo> +- <https://twitter.com/mdo> +- <https://github.com/mdo> **Jacob Thornton** -- <http://twitter.com/fat> -- <http://github.com/fat> +- <https://twitter.com/fat> +- <https://github.com/fat> ## Copyright and license -Code and documentation copyright 2011-2014 Twitter, Inc. Code released under [the MIT license](LICENSE). Docs released under [Creative Commons](docs/LICENSE). +Code and documentation copyright 2011-2015 Twitter, Inc. Code released under [the MIT license](https://github.com/twbs/bootstrap/blob/master/LICENSE). Docs released under [Creative Commons](https://github.com/twbs/bootstrap/blob/master/docs/LICENSE). diff --git a/bower_components/bootstrap/bower.json b/bower_components/bootstrap/bower.json index eaf768a..686bcf1 100644 --- a/bower_components/bootstrap/bower.json +++ b/bower_components/bootstrap/bower.json @@ -1,7 +1,6 @@ { "name": "bootstrap", "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", - "version": "3.2.0", "keywords": [ "css", "js", @@ -13,17 +12,14 @@ "web" ], "homepage": "http://getbootstrap.com", + "license": "MIT", + "moduleType": "globals", "main": [ "less/bootstrap.less", - "dist/css/bootstrap.css", - "dist/js/bootstrap.js", - "dist/fonts/glyphicons-halflings-regular.eot", - "dist/fonts/glyphicons-halflings-regular.svg", - "dist/fonts/glyphicons-halflings-regular.ttf", - "dist/fonts/glyphicons-halflings-regular.woff" + "dist/js/bootstrap.js" ], "ignore": [ - ".*", + "/.*", "_config.yml", "CNAME", "composer.json", @@ -33,6 +29,6 @@ "test-infra" ], "dependencies": { - "jquery": ">= 1.9.0" + "jquery": ">= 1.9.1" } } diff --git a/bower_components/bootstrap/dist/css/bootstrap-theme.css b/bower_components/bootstrap/dist/css/bootstrap-theme.css deleted file mode 100644 index f860bbc..0000000 --- a/bower_components/bootstrap/dist/css/bootstrap-theme.css +++ /dev/null @@ -1,442 +0,0 @@ -/*! - * Bootstrap v3.2.0 (http://getbootstrap.com) - * Copyright 2011-2014 Twitter, Inc. - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ - -.btn-default, -.btn-primary, -.btn-success, -.btn-info, -.btn-warning, -.btn-danger { - text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); -} -.btn-default:active, -.btn-primary:active, -.btn-success:active, -.btn-info:active, -.btn-warning:active, -.btn-danger:active, -.btn-default.active, -.btn-primary.active, -.btn-success.active, -.btn-info.active, -.btn-warning.active, -.btn-danger.active { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); -} -.btn:active, -.btn.active { - background-image: none; -} -.btn-default { - text-shadow: 0 1px 0 #fff; - background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); - background-image: -o-linear-gradient(top, #fff 0%, #e0e0e0 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#e0e0e0)); - background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #dbdbdb; - border-color: #ccc; -} -.btn-default:hover, -.btn-default:focus { - background-color: #e0e0e0; - background-position: 0 -15px; -} -.btn-default:active, -.btn-default.active { - background-color: #e0e0e0; - border-color: #dbdbdb; -} -.btn-default:disabled, -.btn-default[disabled] { - background-color: #e0e0e0; - background-image: none; -} -.btn-primary { - background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); - background-image: -o-linear-gradient(top, #428bca 0%, #2d6ca2 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#2d6ca2)); - background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #2b669a; -} -.btn-primary:hover, -.btn-primary:focus { - background-color: #2d6ca2; - background-position: 0 -15px; -} -.btn-primary:active, -.btn-primary.active { - background-color: #2d6ca2; - border-color: #2b669a; -} -.btn-primary:disabled, -.btn-primary[disabled] { - background-color: #2d6ca2; - background-image: none; -} -.btn-success { - background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); - background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#419641)); - background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #3e8f3e; -} -.btn-success:hover, -.btn-success:focus { - background-color: #419641; - background-position: 0 -15px; -} -.btn-success:active, -.btn-success.active { - background-color: #419641; - border-color: #3e8f3e; -} -.btn-success:disabled, -.btn-success[disabled] { - background-color: #419641; - background-image: none; -} -.btn-info { - background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); - background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#2aabd2)); - background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #28a4c9; -} -.btn-info:hover, -.btn-info:focus { - background-color: #2aabd2; - background-position: 0 -15px; -} -.btn-info:active, -.btn-info.active { - background-color: #2aabd2; - border-color: #28a4c9; -} -.btn-info:disabled, -.btn-info[disabled] { - background-color: #2aabd2; - background-image: none; -} -.btn-warning { - background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); - background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#eb9316)); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #e38d13; -} -.btn-warning:hover, -.btn-warning:focus { - background-color: #eb9316; - background-position: 0 -15px; -} -.btn-warning:active, -.btn-warning.active { - background-color: #eb9316; - border-color: #e38d13; -} -.btn-warning:disabled, -.btn-warning[disabled] { - background-color: #eb9316; - background-image: none; -} -.btn-danger { - background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); - background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c12e2a)); - background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #b92c28; -} -.btn-danger:hover, -.btn-danger:focus { - background-color: #c12e2a; - background-position: 0 -15px; -} -.btn-danger:active, -.btn-danger.active { - background-color: #c12e2a; - border-color: #b92c28; -} -.btn-danger:disabled, -.btn-danger[disabled] { - background-color: #c12e2a; - background-image: none; -} -.thumbnail, -.img-thumbnail { - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); - box-shadow: 0 1px 2px rgba(0, 0, 0, .075); -} -.dropdown-menu > li > a:hover, -.dropdown-menu > li > a:focus { - background-color: #e8e8e8; - background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); - background-repeat: repeat-x; -} -.dropdown-menu > .active > a, -.dropdown-menu > .active > a:hover, -.dropdown-menu > .active > a:focus { - background-color: #357ebd; - background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); - background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); - background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); - background-repeat: repeat-x; -} -.navbar-default { - background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); - background-image: -o-linear-gradient(top, #fff 0%, #f8f8f8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f8f8f8)); - background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); -} -.navbar-default .navbar-nav > .active > a { - background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); - background-image: -o-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f3f3f3)); - background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); - background-repeat: repeat-x; - -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); - box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); -} -.navbar-brand, -.navbar-nav > li > a { - text-shadow: 0 1px 0 rgba(255, 255, 255, .25); -} -.navbar-inverse { - background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); - background-image: -o-linear-gradient(top, #3c3c3c 0%, #222 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#3c3c3c), to(#222)); - background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; -} -.navbar-inverse .navbar-nav > .active > a { - background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%); - background-image: -o-linear-gradient(top, #222 0%, #282828 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#222), to(#282828)); - background-image: linear-gradient(to bottom, #222 0%, #282828 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); - background-repeat: repeat-x; - -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); - box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); -} -.navbar-inverse .navbar-brand, -.navbar-inverse .navbar-nav > li > a { - text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); -} -.navbar-static-top, -.navbar-fixed-top, -.navbar-fixed-bottom { - border-radius: 0; -} -.alert { - text-shadow: 0 1px 0 rgba(255, 255, 255, .2); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); -} -.alert-success { - background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); - background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#c8e5bc)); - background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); - background-repeat: repeat-x; - border-color: #b2dba1; -} -.alert-info { - background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); - background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#b9def0)); - background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); - background-repeat: repeat-x; - border-color: #9acfea; -} -.alert-warning { - background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); - background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#f8efc0)); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); - background-repeat: repeat-x; - border-color: #f5e79e; -} -.alert-danger { - background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); - background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#e7c3c3)); - background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); - background-repeat: repeat-x; - border-color: #dca7a7; -} -.progress { - background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); - background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#ebebeb), to(#f5f5f5)); - background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar { - background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); - background-image: -o-linear-gradient(top, #428bca 0%, #3071a9 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3071a9)); - background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-success { - background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); - background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5cb85c), to(#449d44)); - background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-info { - background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); - background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#5bc0de), to(#31b0d5)); - background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-warning { - background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); - background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f0ad4e), to(#ec971f)); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-danger { - background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); - background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9534f), to(#c9302c)); - background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); - background-repeat: repeat-x; -} -.progress-bar-striped { - background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); - background-image: linear-gradient(45deg, rgba(255, 255, 255, .15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%, transparent 75%, transparent); -} -.list-group { - border-radius: 4px; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); - box-shadow: 0 1px 2px rgba(0, 0, 0, .075); -} -.list-group-item.active, -.list-group-item.active:hover, -.list-group-item.active:focus { - text-shadow: 0 -1px 0 #3071a9; - background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); - background-image: -o-linear-gradient(top, #428bca 0%, #3278b3 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#3278b3)); - background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); - background-repeat: repeat-x; - border-color: #3278b3; -} -.panel { - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); - box-shadow: 0 1px 2px rgba(0, 0, 0, .05); -} -.panel-default > .panel-heading { - background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8)); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); - background-repeat: repeat-x; -} -.panel-primary > .panel-heading { - background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); - background-image: -o-linear-gradient(top, #428bca 0%, #357ebd 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#428bca), to(#357ebd)); - background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); - background-repeat: repeat-x; -} -.panel-success > .panel-heading { - background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); - background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#dff0d8), to(#d0e9c6)); - background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); - background-repeat: repeat-x; -} -.panel-info > .panel-heading { - background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); - background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#d9edf7), to(#c4e3f3)); - background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); - background-repeat: repeat-x; -} -.panel-warning > .panel-heading { - background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); - background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#fcf8e3), to(#faf2cc)); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); - background-repeat: repeat-x; -} -.panel-danger > .panel-heading { - background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); - background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#f2dede), to(#ebcccc)); - background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); - background-repeat: repeat-x; -} -.well { - background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); - background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); - background-image: -webkit-gradient(linear, left top, left bottom, from(#e8e8e8), to(#f5f5f5)); - background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); - background-repeat: repeat-x; - border-color: #dcdcdc; - -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); -} -/*# sourceMappingURL=bootstrap-theme.css.map */ diff --git a/bower_components/bootstrap/dist/css/bootstrap-theme.css.map b/bower_components/bootstrap/dist/css/bootstrap-theme.css.map index 4cc41ab..7535311 100644 --- a/bower_components/bootstrap/dist/css/bootstrap-theme.css.map +++ b/bower_components/bootstrap/dist/css/bootstrap-theme.css.map @@ -1 +1 @@ -{"version":3,"file":"bootstrap-theme.css","sources":["less/theme.less","less/mixins/vendor-prefixes.less","bootstrap-theme.css","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAeA;;;;;;EAME,0CAAA;EC+CA,6FAAA;EACQ,qFAAA;EC5DT;AFiBC;;;;;;;;;;;;EC0CA,0DAAA;EACQ,kDAAA;EC7CT;AFqCC;;EAEE,wBAAA;EEnCH;AFwCD;EG/CI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EA+B2C,2BAAA;EAA2B,oBAAA;EE7BvE;AFAC;;EAEE,2BAAA;EACA,8BAAA;EEEH;AFCC;;EAEE,2BAAA;EACA,uBAAA;EECH;AFEC;;EAEE,2BAAA;EACA,wBAAA;EEAH;AFeD;EGhDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0BD;AFxBC;;EAEE,2BAAA;EACA,8BAAA;EE0BH;AFvBC;;EAEE,2BAAA;EACA,uBAAA;EEyBH;AFtBC;;EAEE,2BAAA;EACA,wBAAA;EEwBH;AFRD;EGjDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkDD;AFhDC;;EAEE,2BAAA;EACA,8BAAA;EEkDH;AF/CC;;EAEE,2BAAA;EACA,uBAAA;EEiDH;AF9CC;;EAEE,2BAAA;EACA,wBAAA;EEgDH;AF/BD;EGlDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0ED;AFxEC;;EAEE,2BAAA;EACA,8BAAA;EE0EH;AFvEC;;EAEE,2BAAA;EACA,uBAAA;EEyEH;AFtEC;;EAEE,2BAAA;EACA,wBAAA;EEwEH;AFtDD;EGnDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EEkGD;AFhGC;;EAEE,2BAAA;EACA,8BAAA;EEkGH;AF/FC;;EAEE,2BAAA;EACA,uBAAA;EEiGH;AF9FC;;EAEE,2BAAA;EACA,wBAAA;EEgGH;AF7ED;EGpDI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EAEA,wHAAA;ECnBF,qEAAA;EJ8BA,6BAAA;EACA,uBAAA;EE0HD;AFxHC;;EAEE,2BAAA;EACA,8BAAA;EE0HH;AFvHC;;EAEE,2BAAA;EACA,uBAAA;EEyHH;AFtHC;;EAEE,2BAAA;EACA,wBAAA;EEwHH;AF7FD;;ECbE,oDAAA;EACQ,4CAAA;EC8GT;AFvFD;;EGvEI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHsEF,2BAAA;EE6FD;AF3FD;;;EG5EI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH4EF,2BAAA;EEiGD;AFvFD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EJ4GA,oBAAA;EC9CA,6FAAA;EACQ,qFAAA;EC4IT;AFlGD;EG1FI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,0DAAA;EACQ,kDAAA;ECqJT;AF/FD;;EAEE,gDAAA;EEiGD;AF7FD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ECnBF,qEAAA;EFgOD;AFrGD;EG5GI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EF2CF,yDAAA;EACQ,iDAAA;EC0KT;AF9GD;;EAWI,2CAAA;EEuGH;AFlGD;;;EAGE,kBAAA;EEoGD;AF1FD;EACE,+CAAA;EC3FA,4FAAA;EACQ,oFAAA;ECwLT;AFlFD;EGtJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8FD;AFzFD;EGvJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsGD;AFhGD;EGxJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EE8GD;AFvGD;EGzJI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EH8IF,uBAAA;EEsHD;AFtGD;EGlKI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED2QH;AFnGD;EG5KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDkRH;AFzGD;EG7KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDyRH;AF/GD;EG9KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDgSH;AFrHD;EG/KI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDuSH;AF3HD;EGhLI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8SH;AF9HD;EGnJI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDoRH;AF1HD;EACE,oBAAA;EC/IA,oDAAA;EACQ,4CAAA;EC4QT;AF3HD;;;EAGE,+BAAA;EGpME,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHkMF,uBAAA;EEiID;AFvHD;ECjKE,mDAAA;EACQ,2CAAA;EC2RT;AFjHD;EG1NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED8UH;AFvHD;EG3NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDqVH;AF7HD;EG5NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED4VH;AFnID;EG7NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDmWH;AFzID;EG9NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;ED0WH;AF/ID;EG/NI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EDiXH;AF9ID;EGvOI,0EAAA;EACA,qEAAA;EACA,+FAAA;EAAA,wEAAA;EACA,6BAAA;EACA,wHAAA;EHqOF,uBAAA;EC1LA,2FAAA;EACQ,mFAAA;EC+UT","sourcesContent":["\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &:disabled,\n &[disabled] {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n}\n\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n &::-moz-placeholder { color: @color; // Firefox\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n",null,"// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]}
\ No newline at end of file +{"version":3,"sources":["bootstrap-theme.css","less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"AAAA;;;;GAIG;ACeH;;;;;;EAME,yCAAA;EC2CA,4FAAA;EACQ,oFAAA;CFvDT;ACgBC;;;;;;;;;;;;ECsCA,yDAAA;EACQ,iDAAA;CFxCT;ACMC;;;;;;;;;;;;;;;;;;ECiCA,yBAAA;EACQ,iBAAA;CFnBT;AC/BD;;;;;;EAuBI,kBAAA;CDgBH;ACyBC;;EAEE,uBAAA;CDvBH;AC4BD;EErEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;EAuC2C,0BAAA;EAA2B,mBAAA;CDjBvE;ACpBC;;EAEE,0BAAA;EACA,6BAAA;CDsBH;ACnBC;;EAEE,0BAAA;EACA,sBAAA;CDqBH;ACfG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD6BL;ACbD;EEtEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CD8DD;AC5DC;;EAEE,0BAAA;EACA,6BAAA;CD8DH;AC3DC;;EAEE,0BAAA;EACA,sBAAA;CD6DH;ACvDG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDqEL;ACpDD;EEvEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CDsGD;ACpGC;;EAEE,0BAAA;EACA,6BAAA;CDsGH;ACnGC;;EAEE,0BAAA;EACA,sBAAA;CDqGH;AC/FG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD6GL;AC3FD;EExEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CD8ID;AC5IC;;EAEE,0BAAA;EACA,6BAAA;CD8IH;AC3IC;;EAEE,0BAAA;EACA,sBAAA;CD6IH;ACvIG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDqJL;AClID;EEzEI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CDsLD;ACpLC;;EAEE,0BAAA;EACA,6BAAA;CDsLH;ACnLC;;EAEE,0BAAA;EACA,sBAAA;CDqLH;AC/KG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CD6LL;ACzKD;EE1EI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EAEA,uHAAA;ECnBF,oEAAA;EH4CA,4BAAA;EACA,sBAAA;CD8ND;AC5NC;;EAEE,0BAAA;EACA,6BAAA;CD8NH;AC3NC;;EAEE,0BAAA;EACA,sBAAA;CD6NH;ACvNG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACA,uBAAA;CDqOL;AC1MD;;EClCE,mDAAA;EACQ,2CAAA;CFgPT;ACrMD;;EE3FI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF0FF,0BAAA;CD2MD;ACzMD;;;EEhGI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EFgGF,0BAAA;CD+MD;ACtMD;EE7GI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ECnBF,oEAAA;EH+HA,mBAAA;ECjEA,4FAAA;EACQ,oFAAA;CF8QT;ACjND;;EE7GI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ED2CF,yDAAA;EACQ,iDAAA;CFwRT;AC9MD;;EAEE,+CAAA;CDgND;AC5MD;EEhII,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ECnBF,oEAAA;EHkJA,mBAAA;CDkND;ACrND;;EEhII,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;ED2CF,wDAAA;EACQ,gDAAA;CF+ST;AC/ND;;EAYI,0CAAA;CDuNH;AClND;;;EAGE,iBAAA;CDoND;AC/LD;EAfI;;;IAGE,YAAA;IE7JF,yEAAA;IACA,oEAAA;IACA,8FAAA;IAAA,uEAAA;IACA,4BAAA;IACA,uHAAA;GH+WD;CACF;AC3MD;EACE,8CAAA;EC3HA,2FAAA;EACQ,mFAAA;CFyUT;ACnMD;EEtLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CD+MD;AC1MD;EEvLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CDuND;ACjND;EExLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CD+ND;ACxND;EEzLI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EF8KF,sBAAA;CDuOD;ACxND;EEjMI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH4ZH;ACrND;EE3MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHmaH;AC3ND;EE5MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH0aH;ACjOD;EE7MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHibH;ACvOD;EE9MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHwbH;AC7OD;EE/MI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH+bH;AChPD;EElLI,8MAAA;EACA,yMAAA;EACA,sMAAA;CHqaH;AC5OD;EACE,mBAAA;EC9KA,mDAAA;EACQ,2CAAA;CF6ZT;AC7OD;;;EAGE,8BAAA;EEnOE,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EFiOF,sBAAA;CDmPD;ACxPD;;;EAQI,kBAAA;CDqPH;AC3OD;ECnME,kDAAA;EACQ,0CAAA;CFibT;ACrOD;EE5PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHoeH;AC3OD;EE7PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CH2eH;ACjPD;EE9PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHkfH;ACvPD;EE/PI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHyfH;AC7PD;EEhQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHggBH;ACnQD;EEjQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;CHugBH;ACnQD;EExQI,yEAAA;EACA,oEAAA;EACA,8FAAA;EAAA,uEAAA;EACA,4BAAA;EACA,uHAAA;EFsQF,sBAAA;EC3NA,0FAAA;EACQ,kFAAA;CFqeT","file":"bootstrap-theme.css","sourcesContent":["/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.btn-default:active,\n.btn-primary:active,\n.btn-success:active,\n.btn-info:active,\n.btn-warning:active,\n.btn-danger:active,\n.btn-default.active,\n.btn-primary.active,\n.btn-success.active,\n.btn-info.active,\n.btn-warning.active,\n.btn-danger.active {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-default.disabled,\n.btn-primary.disabled,\n.btn-success.disabled,\n.btn-info.disabled,\n.btn-warning.disabled,\n.btn-danger.disabled,\n.btn-default[disabled],\n.btn-primary[disabled],\n.btn-success[disabled],\n.btn-info[disabled],\n.btn-warning[disabled],\n.btn-danger[disabled],\nfieldset[disabled] .btn-default,\nfieldset[disabled] .btn-primary,\nfieldset[disabled] .btn-success,\nfieldset[disabled] .btn-info,\nfieldset[disabled] .btn-warning,\nfieldset[disabled] .btn-danger {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-default .badge,\n.btn-primary .badge,\n.btn-success .badge,\n.btn-info .badge,\n.btn-warning .badge,\n.btn-danger .badge {\n text-shadow: none;\n}\n.btn:active,\n.btn.active {\n background-image: none;\n}\n.btn-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #e0e0e0 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #dbdbdb;\n text-shadow: 0 1px 0 #fff;\n border-color: #ccc;\n}\n.btn-default:hover,\n.btn-default:focus {\n background-color: #e0e0e0;\n background-position: 0 -15px;\n}\n.btn-default:active,\n.btn-default.active {\n background-color: #e0e0e0;\n border-color: #dbdbdb;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #e0e0e0;\n background-image: none;\n}\n.btn-primary {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #265a88 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #265a88 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff265a88', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #245580;\n}\n.btn-primary:hover,\n.btn-primary:focus {\n background-color: #265a88;\n background-position: 0 -15px;\n}\n.btn-primary:active,\n.btn-primary.active {\n background-color: #265a88;\n border-color: #245580;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #265a88;\n background-image: none;\n}\n.btn-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #419641 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #3e8f3e;\n}\n.btn-success:hover,\n.btn-success:focus {\n background-color: #419641;\n background-position: 0 -15px;\n}\n.btn-success:active,\n.btn-success.active {\n background-color: #419641;\n border-color: #3e8f3e;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #419641;\n background-image: none;\n}\n.btn-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #28a4c9;\n}\n.btn-info:hover,\n.btn-info:focus {\n background-color: #2aabd2;\n background-position: 0 -15px;\n}\n.btn-info:active,\n.btn-info.active {\n background-color: #2aabd2;\n border-color: #28a4c9;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #2aabd2;\n background-image: none;\n}\n.btn-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #e38d13;\n}\n.btn-warning:hover,\n.btn-warning:focus {\n background-color: #eb9316;\n background-position: 0 -15px;\n}\n.btn-warning:active,\n.btn-warning.active {\n background-color: #eb9316;\n border-color: #e38d13;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #eb9316;\n background-image: none;\n}\n.btn-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c12e2a 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n background-repeat: repeat-x;\n border-color: #b92c28;\n}\n.btn-danger:hover,\n.btn-danger:focus {\n background-color: #c12e2a;\n background-position: 0 -15px;\n}\n.btn-danger:active,\n.btn-danger.active {\n background-color: #c12e2a;\n border-color: #b92c28;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #c12e2a;\n background-image: none;\n}\n.thumbnail,\n.img-thumbnail {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n background-color: #e8e8e8;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n background-color: #2e6da4;\n}\n.navbar-default {\n background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: -o-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);\n background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: -o-linear-gradient(top, #dbdbdb 0%, #e2e2e2 100%);\n background-image: linear-gradient(to bottom, #dbdbdb 0%, #e2e2e2 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdbdbdb', endColorstr='#ffe2e2e2', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);\n}\n.navbar-inverse {\n background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%);\n background-image: -o-linear-gradient(top, #3c3c3c 0%, #222222 100%);\n background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n border-radius: 4px;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .active > a {\n background-image: -webkit-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: -o-linear-gradient(top, #080808 0%, #0f0f0f 100%);\n background-image: linear-gradient(to bottom, #080808 0%, #0f0f0f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff080808', endColorstr='#ff0f0f0f', GradientType=0);\n -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);\n}\n.navbar-inverse .navbar-brand,\n.navbar-inverse .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n@media (max-width: 767px) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #fff;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n }\n}\n.alert {\n text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.alert-success {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);\n border-color: #b2dba1;\n}\n.alert-info {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #b9def0 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);\n border-color: #9acfea;\n}\n.alert-warning {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);\n border-color: #f5e79e;\n}\n.alert-danger {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);\n border-color: #dca7a7;\n}\n.progress {\n background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);\n}\n.progress-bar {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #286090 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #286090 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff286090', GradientType=0);\n}\n.progress-bar-success {\n background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: -o-linear-gradient(top, #5cb85c 0%, #449d44 100%);\n background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);\n}\n.progress-bar-info {\n background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: -o-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);\n background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);\n}\n.progress-bar-warning {\n background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: -o-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);\n background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);\n}\n.progress-bar-danger {\n background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: -o-linear-gradient(top, #d9534f 0%, #c9302c 100%);\n background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);\n}\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.list-group {\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 #286090;\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2b669a 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2b669a 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2b669a', GradientType=0);\n border-color: #2b669a;\n}\n.list-group-item.active .badge,\n.list-group-item.active:hover .badge,\n.list-group-item.active:focus .badge {\n text-shadow: none;\n}\n.panel {\n -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);\n}\n.panel-default > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);\n background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);\n}\n.panel-primary > .panel-heading {\n background-image: -webkit-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: -o-linear-gradient(top, #337ab7 0%, #2e6da4 100%);\n background-image: linear-gradient(to bottom, #337ab7 0%, #2e6da4 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff337ab7', endColorstr='#ff2e6da4', GradientType=0);\n}\n.panel-success > .panel-heading {\n background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: -o-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);\n background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);\n}\n.panel-info > .panel-heading {\n background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: -o-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);\n background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);\n}\n.panel-warning > .panel-heading {\n background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: -o-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);\n background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);\n}\n.panel-danger > .panel-heading {\n background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: -o-linear-gradient(top, #f2dede 0%, #ebcccc 100%);\n background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);\n}\n.well {\n background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: -o-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);\n background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);\n border-color: #dcdcdc;\n -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);\n}\n/*# sourceMappingURL=bootstrap-theme.css.map */","/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n\n//\n// Load core variables and mixins\n// --------------------------------------------------\n\n@import \"variables.less\";\n@import \"mixins.less\";\n\n\n//\n// Buttons\n// --------------------------------------------------\n\n// Common styles\n.btn-default,\n.btn-primary,\n.btn-success,\n.btn-info,\n.btn-warning,\n.btn-danger {\n text-shadow: 0 -1px 0 rgba(0,0,0,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 1px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n // Reset the shadow\n &:active,\n &.active {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n .box-shadow(none);\n }\n\n .badge {\n text-shadow: none;\n }\n}\n\n// Mixin for generating new styles\n.btn-styles(@btn-color: #555) {\n #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n background-image: none;\n }\n }\n}\n\n// Common styles\n.btn {\n // Remove the gradient for the pressed/active state\n &:active,\n &.active {\n background-image: none;\n }\n}\n\n// Apply the mixin to the buttons\n.btn-default { .btn-styles(@btn-default-bg); text-shadow: 0 1px 0 #fff; border-color: #ccc; }\n.btn-primary { .btn-styles(@btn-primary-bg); }\n.btn-success { .btn-styles(@btn-success-bg); }\n.btn-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-bg); }\n\n\n//\n// Images\n// --------------------------------------------------\n\n.thumbnail,\n.img-thumbnail {\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n\n\n//\n// Dropdowns\n// --------------------------------------------------\n\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-hover-bg; @end-color: darken(@dropdown-link-hover-bg, 5%));\n background-color: darken(@dropdown-link-hover-bg, 5%);\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n border-radius: @navbar-border-radius;\n @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075);\n .box-shadow(@shadow);\n\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\n }\n}\n.navbar-brand,\n.navbar-nav > li > a {\n text-shadow: 0 1px 0 rgba(255,255,255,.25);\n}\n\n// Inverted navbar\n.navbar-inverse {\n #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257\n border-radius: @navbar-border-radius;\n .navbar-nav > .open > a,\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\n }\n\n .navbar-brand,\n .navbar-nav > li > a {\n text-shadow: 0 -1px 0 rgba(0,0,0,.25);\n }\n}\n\n// Undo rounded corners in static and fixed navbars\n.navbar-static-top,\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n border-radius: 0;\n}\n\n// Fix active state of dropdown items in collapsed mode\n@media (max-width: @grid-float-breakpoint-max) {\n .navbar .navbar-nav .open .dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: #fff;\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n }\n }\n}\n\n\n//\n// Alerts\n// --------------------------------------------------\n\n// Common styles\n.alert {\n text-shadow: 0 1px 0 rgba(255,255,255,.2);\n @shadow: inset 0 1px 0 rgba(255,255,255,.25), 0 1px 2px rgba(0,0,0,.05);\n .box-shadow(@shadow);\n}\n\n// Mixin for generating new styles\n.alert-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 7.5%));\n border-color: darken(@color, 15%);\n}\n\n// Apply the mixin to the alerts\n.alert-success { .alert-styles(@alert-success-bg); }\n.alert-info { .alert-styles(@alert-info-bg); }\n.alert-warning { .alert-styles(@alert-warning-bg); }\n.alert-danger { .alert-styles(@alert-danger-bg); }\n\n\n//\n// Progress bars\n// --------------------------------------------------\n\n// Give the progress background some depth\n.progress {\n #gradient > .vertical(@start-color: darken(@progress-bg, 4%); @end-color: @progress-bg)\n}\n\n// Mixin for generating new styles\n.progress-bar-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 10%));\n}\n\n// Apply the mixin to the progress bars\n.progress-bar { .progress-bar-styles(@progress-bar-bg); }\n.progress-bar-success { .progress-bar-styles(@progress-bar-success-bg); }\n.progress-bar-info { .progress-bar-styles(@progress-bar-info-bg); }\n.progress-bar-warning { .progress-bar-styles(@progress-bar-warning-bg); }\n.progress-bar-danger { .progress-bar-styles(@progress-bar-danger-bg); }\n\n// Reset the striped class because our mixins don't do multiple gradients and\n// the above custom styles override the new `.progress-bar-striped` in v3.2.0.\n.progress-bar-striped {\n #gradient > .striped();\n}\n\n\n//\n// List groups\n// --------------------------------------------------\n\n.list-group {\n border-radius: @border-radius-base;\n .box-shadow(0 1px 2px rgba(0,0,0,.075));\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%);\n #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%));\n border-color: darken(@list-group-active-border, 7.5%);\n\n .badge {\n text-shadow: none;\n }\n}\n\n\n//\n// Panels\n// --------------------------------------------------\n\n// Common styles\n.panel {\n .box-shadow(0 1px 2px rgba(0,0,0,.05));\n}\n\n// Mixin for generating new styles\n.panel-heading-styles(@color) {\n #gradient > .vertical(@start-color: @color; @end-color: darken(@color, 5%));\n}\n\n// Apply the mixin to the panel headings only\n.panel-default > .panel-heading { .panel-heading-styles(@panel-default-heading-bg); }\n.panel-primary > .panel-heading { .panel-heading-styles(@panel-primary-heading-bg); }\n.panel-success > .panel-heading { .panel-heading-styles(@panel-success-heading-bg); }\n.panel-info > .panel-heading { .panel-heading-styles(@panel-info-heading-bg); }\n.panel-warning > .panel-heading { .panel-heading-styles(@panel-warning-heading-bg); }\n.panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); }\n\n\n//\n// Wells\n// --------------------------------------------------\n\n.well {\n #gradient > .vertical(@start-color: darken(@well-bg, 5%); @end-color: @well-bg);\n border-color: darken(@well-bg, 10%);\n @shadow: inset 0 1px 3px rgba(0,0,0,.05), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n"]}
\ No newline at end of file diff --git a/bower_components/bootstrap/dist/css/bootstrap.css.map b/bower_components/bootstrap/dist/css/bootstrap.css.map index bfb5616..9f60ed2 100644 --- a/bower_components/bootstrap/dist/css/bootstrap.css.map +++ b/bower_components/bootstrap/dist/css/bootstrap.css.map @@ -1 +1 @@ -{"version":3,"file":"bootstrap.css","sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA,6DAA4D;ACQ5D;EACE,yBAAA;EACA,4BAAA;EACA,gCAAA;EDND;ACaD;EACE,WAAA;EDXD;ACuBD;;;;;;;;;;;;EAYE,gBAAA;EDrBD;AC6BD;;;;EAIE,uBAAA;EACA,0BAAA;ED3BD;ACmCD;EACE,eAAA;EACA,WAAA;EDjCD;ACyCD;;EAEE,eAAA;EDvCD;ACiDD;EACE,yBAAA;ED/CD;ACsDD;;EAEE,YAAA;EDpDD;AC8DD;EACE,2BAAA;ED5DD;ACmED;;EAEE,mBAAA;EDjED;ACwED;EACE,oBAAA;EDtED;AC8ED;EACE,gBAAA;EACA,kBAAA;ED5ED;ACmFD;EACE,kBAAA;EACA,aAAA;EDjFD;ACwFD;EACE,gBAAA;EDtFD;AC6FD;;EAEE,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,0BAAA;ED3FD;AC8FD;EACE,aAAA;ED5FD;AC+FD;EACE,iBAAA;ED7FD;ACuGD;EACE,WAAA;EDrGD;AC4GD;EACE,kBAAA;ED1GD;ACoHD;EACE,kBAAA;EDlHD;ACyHD;EACE,8BAAA;EACA,iCAAA;EAAA,yBAAA;EACA,WAAA;EDvHD;AC8HD;EACE,gBAAA;ED5HD;ACmID;;;;EAIE,mCAAA;EACA,gBAAA;EDjID;ACmJD;;;;;EAKE,gBAAA;EACA,eAAA;EACA,WAAA;EDjJD;ACwJD;EACE,mBAAA;EDtJD;ACgKD;;EAEE,sBAAA;ED9JD;ACyKD;;;;EAIE,4BAAA;EACA,iBAAA;EDvKD;AC8KD;;EAEE,iBAAA;ED5KD;ACmLD;;EAEE,WAAA;EACA,YAAA;EDjLD;ACyLD;EACE,qBAAA;EDvLD;ACkMD;;EAEE,gCAAA;EAAA,6BAAA;EAAA,wBAAA;EACA,YAAA;EDhMD;ACyMD;;EAEE,cAAA;EDvMD;ACgND;EACE,+BAAA;EACA,8BAAA;EACA,iCAAA;EACA,yBAAA;ED9MD;ACuND;;EAEE,0BAAA;EDrND;AC4ND;EACE,2BAAA;EACA,eAAA;EACA,gCAAA;ED1ND;ACkOD;EACE,WAAA;EACA,YAAA;EDhOD;ACuOD;EACE,gBAAA;EDrOD;AC6OD;EACE,mBAAA;ED3OD;ACqPD;EACE,2BAAA;EACA,mBAAA;EDnPD;ACsPD;;EAEE,YAAA;EDpPD;AE9ED;EA9FE;IACE,8BAAA;IACA,wBAAA;IACA,oCAAA;IACA,qCAAA;IAAA,6BAAA;IF+KD;EE5KD;;IAEE,4BAAA;IF8KD;EE3KD;IACE,8BAAA;IF6KD;EE1KD;IACE,+BAAA;IF4KD;EExKD;;IAEE,aAAA;IF0KD;EEvKD;;IAEE,wBAAA;IACA,0BAAA;IFyKD;EEtKD;IACE,6BAAA;IFwKD;EErKD;;IAEE,0BAAA;IFuKD;EEpKD;IACE,4BAAA;IFsKD;EEnKD;;;IAGE,YAAA;IACA,WAAA;IFqKD;EElKD;;IAEE,yBAAA;IFoKD;EE/JD;IACE,6BAAA;IFiKD;EE7JD;IACE,eAAA;IF+JD;EE7JD;;IAGI,mCAAA;IF8JH;EE3JD;;IAGI,mCAAA;IF4JH;EEzJD;IACE,wBAAA;IF2JD;EExJD;IACE,sCAAA;IF0JD;EExJD;;IAGI,mCAAA;IFyJH;EACF;AGhPD;EACE,qCAAA;EACA,uDAAA;EACA,6TAAA;EHkPD;AG3OD;EACE,oBAAA;EACA,UAAA;EACA,uBAAA;EACA,qCAAA;EACA,oBAAA;EACA,qBAAA;EACA,gBAAA;EACA,qCAAA;EACA,oCAAA;EH6OD;AGzOmC;EAAW,gBAAA;EH4O9C;AG3OmC;EAAW,gBAAA;EH8O9C;AG7OmC;EAAW,kBAAA;EHgP9C;AG/OmC;EAAW,kBAAA;EHkP9C;AGjPmC;EAAW,kBAAA;EHoP9C;AGnPmC;EAAW,kBAAA;EHsP9C;AGrPmC;EAAW,kBAAA;EHwP9C;AGvPmC;EAAW,kBAAA;EH0P9C;AGzPmC;EAAW,kBAAA;EH4P9C;AG3PmC;EAAW,kBAAA;EH8P9C;AG7PmC;EAAW,kBAAA;EHgQ9C;AG/PmC;EAAW,kBAAA;EHkQ9C;AGjQmC;EAAW,kBAAA;EHoQ9C;AGnQmC;EAAW,kBAAA;EHsQ9C;AGrQmC;EAAW,kBAAA;EHwQ9C;AGvQmC;EAAW,kBAAA;EH0Q9C;AGzQmC;EAAW,kBAAA;EH4Q9C;AG3QmC;EAAW,kBAAA;EH8Q9C;AG7QmC;EAAW,kBAAA;EHgR9C;AG/QmC;EAAW,kBAAA;EHkR9C;AGjRmC;EAAW,kBAAA;EHoR9C;AGnRmC;EAAW,kBAAA;EHsR9C;AGrRmC;EAAW,kBAAA;EHwR9C;AGvRmC;EAAW,kBAAA;EH0R9C;AGzRmC;EAAW,kBAAA;EH4R9C;AG3RmC;EAAW,kBAAA;EH8R9C;AG7RmC;EAAW,kBAAA;EHgS9C;AG/RmC;EAAW,kBAAA;EHkS9C;AGjSmC;EAAW,kBAAA;EHoS9C;AGnSmC;EAAW,kBAAA;EHsS9C;AGrSmC;EAAW,kBAAA;EHwS9C;AGvSmC;EAAW,kBAAA;EH0S9C;AGzSmC;EAAW,kBAAA;EH4S9C;AG3SmC;EAAW,kBAAA;EH8S9C;AG7SmC;EAAW,kBAAA;EHgT9C;AG/SmC;EAAW,kBAAA;EHkT9C;AGjTmC;EAAW,kBAAA;EHoT9C;AGnTmC;EAAW,kBAAA;EHsT9C;AGrTmC;EAAW,kBAAA;EHwT9C;AGvTmC;EAAW,kBAAA;EH0T9C;AGzTmC;EAAW,kBAAA;EH4T9C;AG3TmC;EAAW,kBAAA;EH8T9C;AG7TmC;EAAW,kBAAA;EHgU9C;AG/TmC;EAAW,kBAAA;EHkU9C;AGjUmC;EAAW,kBAAA;EHoU9C;AGnUmC;EAAW,kBAAA;EHsU9C;AGrUmC;EAAW,kBAAA;EHwU9C;AGvUmC;EAAW,kBAAA;EH0U9C;AGzUmC;EAAW,kBAAA;EH4U9C;AG3UmC;EAAW,kBAAA;EH8U9C;AG7UmC;EAAW,kBAAA;EHgV9C;AG/UmC;EAAW,kBAAA;EHkV9C;AGjVmC;EAAW,kBAAA;EHoV9C;AGnVmC;EAAW,kBAAA;EHsV9C;AGrVmC;EAAW,kBAAA;EHwV9C;AGvVmC;EAAW,kBAAA;EH0V9C;AGzVmC;EAAW,kBAAA;EH4V9C;AG3VmC;EAAW,kBAAA;EH8V9C;AG7VmC;EAAW,kBAAA;EHgW9C;AG/VmC;EAAW,kBAAA;EHkW9C;AGjWmC;EAAW,kBAAA;EHoW9C;AGnWmC;EAAW,kBAAA;EHsW9C;AGrWmC;EAAW,kBAAA;EHwW9C;AGvWmC;EAAW,kBAAA;EH0W9C;AGzWmC;EAAW,kBAAA;EH4W9C;AG3WmC;EAAW,kBAAA;EH8W9C;AG7WmC;EAAW,kBAAA;EHgX9C;AG/WmC;EAAW,kBAAA;EHkX9C;AGjXmC;EAAW,kBAAA;EHoX9C;AGnXmC;EAAW,kBAAA;EHsX9C;AGrXmC;EAAW,kBAAA;EHwX9C;AGvXmC;EAAW,kBAAA;EH0X9C;AGzXmC;EAAW,kBAAA;EH4X9C;AG3XmC;EAAW,kBAAA;EH8X9C;AG7XmC;EAAW,kBAAA;EHgY9C;AG/XmC;EAAW,kBAAA;EHkY9C;AGjYmC;EAAW,kBAAA;EHoY9C;AGnYmC;EAAW,kBAAA;EHsY9C;AGrYmC;EAAW,kBAAA;EHwY9C;AGvYmC;EAAW,kBAAA;EH0Y9C;AGzYmC;EAAW,kBAAA;EH4Y9C;AG3YmC;EAAW,kBAAA;EH8Y9C;AG7YmC;EAAW,kBAAA;EHgZ9C;AG/YmC;EAAW,kBAAA;EHkZ9C;AGjZmC;EAAW,kBAAA;EHoZ9C;AGnZmC;EAAW,kBAAA;EHsZ9C;AGrZmC;EAAW,kBAAA;EHwZ9C;AGvZmC;EAAW,kBAAA;EH0Z9C;AGzZmC;EAAW,kBAAA;EH4Z9C;AG3ZmC;EAAW,kBAAA;EH8Z9C;AG7ZmC;EAAW,kBAAA;EHga9C;AG/ZmC;EAAW,kBAAA;EHka9C;AGjamC;EAAW,kBAAA;EHoa9C;AGnamC;EAAW,kBAAA;EHsa9C;AGramC;EAAW,kBAAA;EHwa9C;AGvamC;EAAW,kBAAA;EH0a9C;AGzamC;EAAW,kBAAA;EH4a9C;AG3amC;EAAW,kBAAA;EH8a9C;AG7amC;EAAW,kBAAA;EHgb9C;AG/amC;EAAW,kBAAA;EHkb9C;AGjbmC;EAAW,kBAAA;EHob9C;AGnbmC;EAAW,kBAAA;EHsb9C;AGrbmC;EAAW,kBAAA;EHwb9C;AGvbmC;EAAW,kBAAA;EH0b9C;AGzbmC;EAAW,kBAAA;EH4b9C;AG3bmC;EAAW,kBAAA;EH8b9C;AG7bmC;EAAW,kBAAA;EHgc9C;AG/bmC;EAAW,kBAAA;EHkc9C;AGjcmC;EAAW,kBAAA;EHoc9C;AGncmC;EAAW,kBAAA;EHsc9C;AGrcmC;EAAW,kBAAA;EHwc9C;AGvcmC;EAAW,kBAAA;EH0c9C;AGzcmC;EAAW,kBAAA;EH4c9C;AG3cmC;EAAW,kBAAA;EH8c9C;AG7cmC;EAAW,kBAAA;EHgd9C;AG/cmC;EAAW,kBAAA;EHkd9C;AGjdmC;EAAW,kBAAA;EHod9C;AGndmC;EAAW,kBAAA;EHsd9C;AGrdmC;EAAW,kBAAA;EHwd9C;AGvdmC;EAAW,kBAAA;EH0d9C;AGzdmC;EAAW,kBAAA;EH4d9C;AG3dmC;EAAW,kBAAA;EH8d9C;AG7dmC;EAAW,kBAAA;EHge9C;AG/dmC;EAAW,kBAAA;EHke9C;AGjemC;EAAW,kBAAA;EHoe9C;AGnemC;EAAW,kBAAA;EHse9C;AGremC;EAAW,kBAAA;EHwe9C;AGvemC;EAAW,kBAAA;EH0e9C;AGzemC;EAAW,kBAAA;EH4e9C;AG3emC;EAAW,kBAAA;EH8e9C;AG7emC;EAAW,kBAAA;EHgf9C;AG/emC;EAAW,kBAAA;EHkf9C;AGjfmC;EAAW,kBAAA;EHof9C;AGnfmC;EAAW,kBAAA;EHsf9C;AGrfmC;EAAW,kBAAA;EHwf9C;AGvfmC;EAAW,kBAAA;EH0f9C;AGzfmC;EAAW,kBAAA;EH4f9C;AG3fmC;EAAW,kBAAA;EH8f9C;AG7fmC;EAAW,kBAAA;EHggB9C;AG/fmC;EAAW,kBAAA;EHkgB9C;AGjgBmC;EAAW,kBAAA;EHogB9C;AGngBmC;EAAW,kBAAA;EHsgB9C;AGrgBmC;EAAW,kBAAA;EHwgB9C;AGvgBmC;EAAW,kBAAA;EH0gB9C;AGzgBmC;EAAW,kBAAA;EH4gB9C;AG3gBmC;EAAW,kBAAA;EH8gB9C;AG7gBmC;EAAW,kBAAA;EHghB9C;AG/gBmC;EAAW,kBAAA;EHkhB9C;AGjhBmC;EAAW,kBAAA;EHohB9C;AGnhBmC;EAAW,kBAAA;EHshB9C;AGrhBmC;EAAW,kBAAA;EHwhB9C;AGvhBmC;EAAW,kBAAA;EH0hB9C;AGzhBmC;EAAW,kBAAA;EH4hB9C;AG3hBmC;EAAW,kBAAA;EH8hB9C;AG7hBmC;EAAW,kBAAA;EHgiB9C;AG/hBmC;EAAW,kBAAA;EHkiB9C;AGjiBmC;EAAW,kBAAA;EHoiB9C;AGniBmC;EAAW,kBAAA;EHsiB9C;AGriBmC;EAAW,kBAAA;EHwiB9C;AGviBmC;EAAW,kBAAA;EH0iB9C;AGziBmC;EAAW,kBAAA;EH4iB9C;AG3iBmC;EAAW,kBAAA;EH8iB9C;AG7iBmC;EAAW,kBAAA;EHgjB9C;AG/iBmC;EAAW,kBAAA;EHkjB9C;AGjjBmC;EAAW,kBAAA;EHojB9C;AGnjBmC;EAAW,kBAAA;EHsjB9C;AGrjBmC;EAAW,kBAAA;EHwjB9C;AGvjBmC;EAAW,kBAAA;EH0jB9C;AGzjBmC;EAAW,kBAAA;EH4jB9C;AG3jBmC;EAAW,kBAAA;EH8jB9C;AG7jBmC;EAAW,kBAAA;EHgkB9C;AG/jBmC;EAAW,kBAAA;EHkkB9C;AGjkBmC;EAAW,kBAAA;EHokB9C;AGnkBmC;EAAW,kBAAA;EHskB9C;AGrkBmC;EAAW,kBAAA;EHwkB9C;AGvkBmC;EAAW,kBAAA;EH0kB9C;AGzkBmC;EAAW,kBAAA;EH4kB9C;AG3kBmC;EAAW,kBAAA;EH8kB9C;AG7kBmC;EAAW,kBAAA;EHglB9C;AG/kBmC;EAAW,kBAAA;EHklB9C;AGjlBmC;EAAW,kBAAA;EHolB9C;AGnlBmC;EAAW,kBAAA;EHslB9C;AGrlBmC;EAAW,kBAAA;EHwlB9C;AGvlBmC;EAAW,kBAAA;EH0lB9C;AGzlBmC;EAAW,kBAAA;EH4lB9C;AG3lBmC;EAAW,kBAAA;EH8lB9C;AG7lBmC;EAAW,kBAAA;EHgmB9C;AG/lBmC;EAAW,kBAAA;EHkmB9C;AGjmBmC;EAAW,kBAAA;EHomB9C;AGnmBmC;EAAW,kBAAA;EHsmB9C;AGrmBmC;EAAW,kBAAA;EHwmB9C;AGvmBmC;EAAW,kBAAA;EH0mB9C;AGzmBmC;EAAW,kBAAA;EH4mB9C;AG3mBmC;EAAW,kBAAA;EH8mB9C;AG7mBmC;EAAW,kBAAA;EHgnB9C;AG/mBmC;EAAW,kBAAA;EHknB9C;AGjnBmC;EAAW,kBAAA;EHonB9C;AGnnBmC;EAAW,kBAAA;EHsnB9C;AGrnBmC;EAAW,kBAAA;EHwnB9C;AGvnBmC;EAAW,kBAAA;EH0nB9C;AIx1BD;ECgEE,gCAAA;EACG,6BAAA;EACK,wBAAA;EL2xBT;AI11BD;;EC6DE,gCAAA;EACG,6BAAA;EACK,wBAAA;ELiyBT;AIx1BD;EACE,iBAAA;EACA,+CAAA;EJ01BD;AIv1BD;EACE,6DAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,2BAAA;EJy1BD;AIr1BD;;;;EAIE,sBAAA;EACA,oBAAA;EACA,sBAAA;EJu1BD;AIj1BD;EACE,gBAAA;EACA,uBAAA;EJm1BD;AIj1BC;;EAEE,gBAAA;EACA,4BAAA;EJm1BH;AIh1BC;EErDA,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENu4BD;AI10BD;EACE,WAAA;EJ40BD;AIt0BD;EACE,wBAAA;EJw0BD;AIp0BD;;;;;EGvEE,gBAAA;EACA,gBAAA;EACA,iBAAA;EACA,cAAA;EPk5BD;AIz0BD;EACE,oBAAA;EJ20BD;AIr0BD;EACE,cAAA;EACA,yBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EC0FA,0CAAA;EACK,qCAAA;EACG,kCAAA;EEpLR,uBAAA;EACA,gBAAA;EACA,iBAAA;EACA,cAAA;EPm6BD;AIt0BD;EACE,oBAAA;EJw0BD;AIl0BD;EACE,kBAAA;EACA,qBAAA;EACA,WAAA;EACA,+BAAA;EJo0BD;AI5zBD;EACE,oBAAA;EACA,YAAA;EACA,aAAA;EACA,cAAA;EACA,YAAA;EACA,kBAAA;EACA,wBAAA;EACA,WAAA;EJ8zBD;AItzBC;;EAEE,kBAAA;EACA,aAAA;EACA,cAAA;EACA,WAAA;EACA,mBAAA;EACA,YAAA;EJwzBH;AQn8BD;;;;;;;;;;;;EAEE,sBAAA;EACA,kBAAA;EACA,kBAAA;EACA,gBAAA;ER+8BD;AQp9BD;;;;;;;;;;;;;;;;;;;;;;;;EASI,qBAAA;EACA,gBAAA;EACA,gBAAA;ERq+BH;AQj+BD;;;;;;EAGE,kBAAA;EACA,qBAAA;ERs+BD;AQ1+BD;;;;;;;;;;;;EAQI,gBAAA;ERg/BH;AQ7+BD;;;;;;EAGE,kBAAA;EACA,qBAAA;ERk/BD;AQt/BD;;;;;;;;;;;;EAQI,gBAAA;ER4/BH;AQx/BD;;EAAU,iBAAA;ER4/BT;AQ3/BD;;EAAU,iBAAA;ER+/BT;AQ9/BD;;EAAU,iBAAA;ERkgCT;AQjgCD;;EAAU,iBAAA;ERqgCT;AQpgCD;;EAAU,iBAAA;ERwgCT;AQvgCD;;EAAU,iBAAA;ER2gCT;AQrgCD;EACE,kBAAA;ERugCD;AQpgCD;EACE,qBAAA;EACA,iBAAA;EACA,kBAAA;EACA,kBAAA;ERsgCD;AQjgCD;EAAA;IAFI,iBAAA;IRugCD;EACF;AQ//BD;;EAEE,gBAAA;ERigCD;AQ7/BD;EACE,oBAAA;ER+/BD;AQ5/BD;;EAEE,2BAAA;EACA,eAAA;ER8/BD;AQ1/BD;EAAuB,kBAAA;ER6/BtB;AQ5/BD;EAAuB,mBAAA;ER+/BtB;AQ9/BD;EAAuB,oBAAA;ERigCtB;AQhgCD;EAAuB,qBAAA;ERmgCtB;AQlgCD;EAAuB,qBAAA;ERqgCtB;AQlgCD;EAAuB,2BAAA;ERqgCtB;AQpgCD;EAAuB,2BAAA;ERugCtB;AQtgCD;EAAuB,4BAAA;ERygCtB;AQtgCD;EACE,gBAAA;ERwgCD;AQtgCD;EC1GE,gBAAA;ETmnCD;ASlnCC;EACE,gBAAA;ETonCH;AQzgCD;EC7GE,gBAAA;ETynCD;ASxnCC;EACE,gBAAA;ET0nCH;AQ5gCD;EChHE,gBAAA;ET+nCD;AS9nCC;EACE,gBAAA;ETgoCH;AQ/gCD;ECnHE,gBAAA;ETqoCD;ASpoCC;EACE,gBAAA;ETsoCH;AQlhCD;ECtHE,gBAAA;ET2oCD;AS1oCC;EACE,gBAAA;ET4oCH;AQjhCD;EAGE,aAAA;EEhIA,2BAAA;EVkpCD;AUjpCC;EACE,2BAAA;EVmpCH;AQlhCD;EEnIE,2BAAA;EVwpCD;AUvpCC;EACE,2BAAA;EVypCH;AQrhCD;EEtIE,2BAAA;EV8pCD;AU7pCC;EACE,2BAAA;EV+pCH;AQxhCD;EEzIE,2BAAA;EVoqCD;AUnqCC;EACE,2BAAA;EVqqCH;AQ3hCD;EE5IE,2BAAA;EV0qCD;AUzqCC;EACE,2BAAA;EV2qCH;AQzhCD;EACE,qBAAA;EACA,qBAAA;EACA,kCAAA;ER2hCD;AQnhCD;;EAEE,eAAA;EACA,qBAAA;ERqhCD;AQxhCD;;;;EAMI,kBAAA;ERwhCH;AQjhCD;EACE,iBAAA;EACA,kBAAA;ERmhCD;AQ/gCD;EALE,iBAAA;EACA,kBAAA;EAMA,mBAAA;ERkhCD;AQphCD;EAKI,uBAAA;EACA,mBAAA;EACA,oBAAA;ERkhCH;AQ7gCD;EACE,eAAA;EACA,qBAAA;ER+gCD;AQ7gCD;;EAEE,yBAAA;ER+gCD;AQ7gCD;EACE,mBAAA;ER+gCD;AQ7gCD;EACE,gBAAA;ER+gCD;AQt/BD;EAAA;IAVM,aAAA;IACA,cAAA;IACA,aAAA;IACA,mBAAA;IG3NJ,kBAAA;IACA,yBAAA;IACA,qBAAA;IXguCC;EQhgCH;IAHM,oBAAA;IRsgCH;EACF;AQ7/BD;;EAGE,cAAA;EACA,mCAAA;ER8/BD;AQ5/BD;EACE,gBAAA;EACA,2BAAA;ER8/BD;AQ1/BD;EACE,oBAAA;EACA,kBAAA;EACA,mBAAA;EACA,gCAAA;ER4/BD;AQv/BG;;;EACE,kBAAA;ER2/BL;AQrgCD;;;EAmBI,gBAAA;EACA,gBAAA;EACA,yBAAA;EACA,gBAAA;ERu/BH;AQr/BG;;;EACE,wBAAA;ERy/BL;AQj/BD;;EAEE,qBAAA;EACA,iBAAA;EACA,iCAAA;EACA,gBAAA;EACA,mBAAA;ERm/BD;AQ7+BG;;;;;;EAAW,aAAA;ERq/Bd;AQp/BG;;;;;;EACE,wBAAA;ER2/BL;AQr/BD;;EAEE,aAAA;ERu/BD;AQn/BD;EACE,qBAAA;EACA,oBAAA;EACA,yBAAA;ERq/BD;AYtyCD;;;;EAIE,gEAAA;EZwyCD;AYpyCD;EACE,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,2BAAA;EACA,oBAAA;EZsyCD;AYlyCD;EACE,kBAAA;EACA,gBAAA;EACA,gBAAA;EACA,2BAAA;EACA,oBAAA;EACA,wDAAA;EAAA,gDAAA;EZoyCD;AY1yCD;EASI,YAAA;EACA,iBAAA;EACA,0BAAA;EAAA,kBAAA;EZoyCH;AY/xCD;EACE,gBAAA;EACA,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,uBAAA;EACA,uBAAA;EACA,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EZiyCD;AY5yCD;EAeI,YAAA;EACA,oBAAA;EACA,gBAAA;EACA,uBAAA;EACA,+BAAA;EACA,kBAAA;EZgyCH;AY3xCD;EACE,mBAAA;EACA,oBAAA;EZ6xCD;Aat1CD;ECHE,oBAAA;EACA,mBAAA;EACA,oBAAA;EACA,qBAAA;Ed41CD;Aat1CC;EAAA;IAFE,cAAA;Ib41CD;EACF;Aax1CC;EAAA;IAFE,cAAA;Ib81CD;EACF;Aa11CD;EAAA;IAFI,eAAA;Ibg2CD;EACF;Aav1CD;ECvBE,oBAAA;EACA,mBAAA;EACA,oBAAA;EACA,qBAAA;Edi3CD;Aap1CD;ECvBE,oBAAA;EACA,qBAAA;Ed82CD;Ae92CG;EACE,oBAAA;EAEA,iBAAA;EAEA,oBAAA;EACA,qBAAA;Ef82CL;Ae91CG;EACE,aAAA;Efg2CL;Aez1CC;EACE,aAAA;Ef21CH;Ae51CC;EACE,qBAAA;Ef81CH;Ae/1CC;EACE,qBAAA;Efi2CH;Ael2CC;EACE,YAAA;Efo2CH;Aer2CC;EACE,qBAAA;Efu2CH;Aex2CC;EACE,qBAAA;Ef02CH;Ae32CC;EACE,YAAA;Ef62CH;Ae92CC;EACE,qBAAA;Efg3CH;Aej3CC;EACE,qBAAA;Efm3CH;Aep3CC;EACE,YAAA;Efs3CH;Aev3CC;EACE,qBAAA;Efy3CH;Ae13CC;EACE,oBAAA;Ef43CH;Ae92CC;EACE,aAAA;Efg3CH;Aej3CC;EACE,qBAAA;Efm3CH;Aep3CC;EACE,qBAAA;Efs3CH;Aev3CC;EACE,YAAA;Efy3CH;Ae13CC;EACE,qBAAA;Ef43CH;Ae73CC;EACE,qBAAA;Ef+3CH;Aeh4CC;EACE,YAAA;Efk4CH;Aen4CC;EACE,qBAAA;Efq4CH;Aet4CC;EACE,qBAAA;Efw4CH;Aez4CC;EACE,YAAA;Ef24CH;Ae54CC;EACE,qBAAA;Ef84CH;Ae/4CC;EACE,oBAAA;Efi5CH;Ae74CC;EACE,aAAA;Ef+4CH;Ae/5CC;EACE,YAAA;Efi6CH;Ael6CC;EACE,oBAAA;Efo6CH;Aer6CC;EACE,oBAAA;Efu6CH;Aex6CC;EACE,WAAA;Ef06CH;Ae36CC;EACE,oBAAA;Ef66CH;Ae96CC;EACE,oBAAA;Efg7CH;Aej7CC;EACE,WAAA;Efm7CH;Aep7CC;EACE,oBAAA;Efs7CH;Aev7CC;EACE,oBAAA;Efy7CH;Ae17CC;EACE,WAAA;Ef47CH;Ae77CC;EACE,oBAAA;Ef+7CH;Aeh8CC;EACE,mBAAA;Efk8CH;Ae97CC;EACE,YAAA;Efg8CH;Ael7CC;EACE,mBAAA;Efo7CH;Aer7CC;EACE,2BAAA;Efu7CH;Aex7CC;EACE,2BAAA;Ef07CH;Ae37CC;EACE,kBAAA;Ef67CH;Ae97CC;EACE,2BAAA;Efg8CH;Aej8CC;EACE,2BAAA;Efm8CH;Aep8CC;EACE,kBAAA;Efs8CH;Aev8CC;EACE,2BAAA;Efy8CH;Ae18CC;EACE,2BAAA;Ef48CH;Ae78CC;EACE,kBAAA;Ef+8CH;Aeh9CC;EACE,2BAAA;Efk9CH;Aen9CC;EACE,0BAAA;Efq9CH;Aet9CC;EACE,iBAAA;Efw9CH;Aa59CD;EE9BI;IACE,aAAA;If6/CH;Eet/CD;IACE,aAAA;Ifw/CD;Eez/CD;IACE,qBAAA;If2/CD;Ee5/CD;IACE,qBAAA;If8/CD;Ee//CD;IACE,YAAA;IfigDD;EelgDD;IACE,qBAAA;IfogDD;EergDD;IACE,qBAAA;IfugDD;EexgDD;IACE,YAAA;If0gDD;Ee3gDD;IACE,qBAAA;If6gDD;Ee9gDD;IACE,qBAAA;IfghDD;EejhDD;IACE,YAAA;IfmhDD;EephDD;IACE,qBAAA;IfshDD;EevhDD;IACE,oBAAA;IfyhDD;Ee3gDD;IACE,aAAA;If6gDD;Ee9gDD;IACE,qBAAA;IfghDD;EejhDD;IACE,qBAAA;IfmhDD;EephDD;IACE,YAAA;IfshDD;EevhDD;IACE,qBAAA;IfyhDD;Ee1hDD;IACE,qBAAA;If4hDD;Ee7hDD;IACE,YAAA;If+hDD;EehiDD;IACE,qBAAA;IfkiDD;EeniDD;IACE,qBAAA;IfqiDD;EetiDD;IACE,YAAA;IfwiDD;EeziDD;IACE,qBAAA;If2iDD;Ee5iDD;IACE,oBAAA;If8iDD;Ee1iDD;IACE,aAAA;If4iDD;Ee5jDD;IACE,YAAA;If8jDD;Ee/jDD;IACE,oBAAA;IfikDD;EelkDD;IACE,oBAAA;IfokDD;EerkDD;IACE,WAAA;IfukDD;EexkDD;IACE,oBAAA;If0kDD;Ee3kDD;IACE,oBAAA;If6kDD;Ee9kDD;IACE,WAAA;IfglDD;EejlDD;IACE,oBAAA;IfmlDD;EeplDD;IACE,oBAAA;IfslDD;EevlDD;IACE,WAAA;IfylDD;Ee1lDD;IACE,oBAAA;If4lDD;Ee7lDD;IACE,mBAAA;If+lDD;Ee3lDD;IACE,YAAA;If6lDD;Ee/kDD;IACE,mBAAA;IfilDD;EellDD;IACE,2BAAA;IfolDD;EerlDD;IACE,2BAAA;IfulDD;EexlDD;IACE,kBAAA;If0lDD;Ee3lDD;IACE,2BAAA;If6lDD;Ee9lDD;IACE,2BAAA;IfgmDD;EejmDD;IACE,kBAAA;IfmmDD;EepmDD;IACE,2BAAA;IfsmDD;EevmDD;IACE,2BAAA;IfymDD;Ee1mDD;IACE,kBAAA;If4mDD;Ee7mDD;IACE,2BAAA;If+mDD;EehnDD;IACE,0BAAA;IfknDD;EennDD;IACE,iBAAA;IfqnDD;EACF;AajnDD;EEvCI;IACE,aAAA;If2pDH;EeppDD;IACE,aAAA;IfspDD;EevpDD;IACE,qBAAA;IfypDD;Ee1pDD;IACE,qBAAA;If4pDD;Ee7pDD;IACE,YAAA;If+pDD;EehqDD;IACE,qBAAA;IfkqDD;EenqDD;IACE,qBAAA;IfqqDD;EetqDD;IACE,YAAA;IfwqDD;EezqDD;IACE,qBAAA;If2qDD;Ee5qDD;IACE,qBAAA;If8qDD;Ee/qDD;IACE,YAAA;IfirDD;EelrDD;IACE,qBAAA;IforDD;EerrDD;IACE,oBAAA;IfurDD;EezqDD;IACE,aAAA;If2qDD;Ee5qDD;IACE,qBAAA;If8qDD;Ee/qDD;IACE,qBAAA;IfirDD;EelrDD;IACE,YAAA;IforDD;EerrDD;IACE,qBAAA;IfurDD;EexrDD;IACE,qBAAA;If0rDD;Ee3rDD;IACE,YAAA;If6rDD;Ee9rDD;IACE,qBAAA;IfgsDD;EejsDD;IACE,qBAAA;IfmsDD;EepsDD;IACE,YAAA;IfssDD;EevsDD;IACE,qBAAA;IfysDD;Ee1sDD;IACE,oBAAA;If4sDD;EexsDD;IACE,aAAA;If0sDD;Ee1tDD;IACE,YAAA;If4tDD;Ee7tDD;IACE,oBAAA;If+tDD;EehuDD;IACE,oBAAA;IfkuDD;EenuDD;IACE,WAAA;IfquDD;EetuDD;IACE,oBAAA;IfwuDD;EezuDD;IACE,oBAAA;If2uDD;Ee5uDD;IACE,WAAA;If8uDD;Ee/uDD;IACE,oBAAA;IfivDD;EelvDD;IACE,oBAAA;IfovDD;EervDD;IACE,WAAA;IfuvDD;EexvDD;IACE,oBAAA;If0vDD;Ee3vDD;IACE,mBAAA;If6vDD;EezvDD;IACE,YAAA;If2vDD;Ee7uDD;IACE,mBAAA;If+uDD;EehvDD;IACE,2BAAA;IfkvDD;EenvDD;IACE,2BAAA;IfqvDD;EetvDD;IACE,kBAAA;IfwvDD;EezvDD;IACE,2BAAA;If2vDD;Ee5vDD;IACE,2BAAA;If8vDD;Ee/vDD;IACE,kBAAA;IfiwDD;EelwDD;IACE,2BAAA;IfowDD;EerwDD;IACE,2BAAA;IfuwDD;EexwDD;IACE,kBAAA;If0wDD;Ee3wDD;IACE,2BAAA;If6wDD;Ee9wDD;IACE,0BAAA;IfgxDD;EejxDD;IACE,iBAAA;IfmxDD;EACF;AaxwDD;EE9CI;IACE,aAAA;IfyzDH;EelzDD;IACE,aAAA;IfozDD;EerzDD;IACE,qBAAA;IfuzDD;EexzDD;IACE,qBAAA;If0zDD;Ee3zDD;IACE,YAAA;If6zDD;Ee9zDD;IACE,qBAAA;Ifg0DD;Eej0DD;IACE,qBAAA;Ifm0DD;Eep0DD;IACE,YAAA;Ifs0DD;Eev0DD;IACE,qBAAA;Ify0DD;Ee10DD;IACE,qBAAA;If40DD;Ee70DD;IACE,YAAA;If+0DD;Eeh1DD;IACE,qBAAA;Ifk1DD;Een1DD;IACE,oBAAA;Ifq1DD;Eev0DD;IACE,aAAA;Ify0DD;Ee10DD;IACE,qBAAA;If40DD;Ee70DD;IACE,qBAAA;If+0DD;Eeh1DD;IACE,YAAA;Ifk1DD;Een1DD;IACE,qBAAA;Ifq1DD;Eet1DD;IACE,qBAAA;Ifw1DD;Eez1DD;IACE,YAAA;If21DD;Ee51DD;IACE,qBAAA;If81DD;Ee/1DD;IACE,qBAAA;Ifi2DD;Eel2DD;IACE,YAAA;Ifo2DD;Eer2DD;IACE,qBAAA;Ifu2DD;Eex2DD;IACE,oBAAA;If02DD;Eet2DD;IACE,aAAA;Ifw2DD;Eex3DD;IACE,YAAA;If03DD;Ee33DD;IACE,oBAAA;If63DD;Ee93DD;IACE,oBAAA;Ifg4DD;Eej4DD;IACE,WAAA;Ifm4DD;Eep4DD;IACE,oBAAA;Ifs4DD;Eev4DD;IACE,oBAAA;Ify4DD;Ee14DD;IACE,WAAA;If44DD;Ee74DD;IACE,oBAAA;If+4DD;Eeh5DD;IACE,oBAAA;Ifk5DD;Een5DD;IACE,WAAA;Ifq5DD;Eet5DD;IACE,oBAAA;Ifw5DD;Eez5DD;IACE,mBAAA;If25DD;Eev5DD;IACE,YAAA;Ify5DD;Ee34DD;IACE,mBAAA;If64DD;Ee94DD;IACE,2BAAA;Ifg5DD;Eej5DD;IACE,2BAAA;Ifm5DD;Eep5DD;IACE,kBAAA;Ifs5DD;Eev5DD;IACE,2BAAA;Ify5DD;Ee15DD;IACE,2BAAA;If45DD;Ee75DD;IACE,kBAAA;If+5DD;Eeh6DD;IACE,2BAAA;Ifk6DD;Een6DD;IACE,2BAAA;Ifq6DD;Eet6DD;IACE,kBAAA;Ifw6DD;Eez6DD;IACE,2BAAA;If26DD;Ee56DD;IACE,0BAAA;If86DD;Ee/6DD;IACE,iBAAA;Ifi7DD;EACF;AgBr/DD;EACE,+BAAA;EhBu/DD;AgBr/DD;EACE,kBAAA;EhBu/DD;AgBj/DD;EACE,aAAA;EACA,iBAAA;EACA,qBAAA;EhBm/DD;AgBt/DD;;;;;;EAWQ,cAAA;EACA,yBAAA;EACA,qBAAA;EACA,+BAAA;EhBm/DP;AgBjgED;EAoBI,wBAAA;EACA,kCAAA;EhBg/DH;AgBrgED;;;;;;EA8BQ,eAAA;EhB++DP;AgB7gED;EAoCI,+BAAA;EhB4+DH;AgBhhED;EAyCI,2BAAA;EhB0+DH;AgBn+DD;;;;;;EAOQ,cAAA;EhBo+DP;AgBz9DD;EACE,2BAAA;EhB29DD;AgB59DD;;;;;;EAQQ,2BAAA;EhB49DP;AgBp+DD;;EAeM,0BAAA;EhBy9DL;AgB/8DD;;EAIM,2BAAA;EhB+8DL;AgBr8DD;;EAIM,2BAAA;EhBq8DL;AgB37DD;EACE,kBAAA;EACA,aAAA;EACA,uBAAA;EhB67DD;AgBx7DG;;EACE,kBAAA;EACA,aAAA;EACA,qBAAA;EhB27DL;AiBvkEC;;;;;;;;;;;;EAOI,2BAAA;EjB8kEL;AiBxkEC;;;;;EAMI,2BAAA;EjBykEL;AiB5lEC;;;;;;;;;;;;EAOI,2BAAA;EjBmmEL;AiB7lEC;;;;;EAMI,2BAAA;EjB8lEL;AiBjnEC;;;;;;;;;;;;EAOI,2BAAA;EjBwnEL;AiBlnEC;;;;;EAMI,2BAAA;EjBmnEL;AiBtoEC;;;;;;;;;;;;EAOI,2BAAA;EjB6oEL;AiBvoEC;;;;;EAMI,2BAAA;EjBwoEL;AiB3pEC;;;;;;;;;;;;EAOI,2BAAA;EjBkqEL;AiB5pEC;;;;;EAMI,2BAAA;EjB6pEL;AgB78DD;EAAA;IA5DI,aAAA;IACA,qBAAA;IACA,oBAAA;IACA,kBAAA;IACA,8CAAA;IACA,2BAAA;IACA,mCAAA;IhB6gED;EgBv9DH;IAlDM,kBAAA;IhB4gEH;EgB19DH;;;;;;IAzCY,qBAAA;IhB2gET;EgBl+DH;IAjCM,WAAA;IhBsgEH;EgBr+DH;;;;;;IAxBY,gBAAA;IhBqgET;EgB7+DH;;;;;;IApBY,iBAAA;IhBygET;EgBr/DH;;;;IAPY,kBAAA;IhBkgET;EACF;AkB3tED;EACE,YAAA;EACA,WAAA;EACA,WAAA;EAIA,cAAA;ElB0tED;AkBvtED;EACE,gBAAA;EACA,aAAA;EACA,YAAA;EACA,qBAAA;EACA,iBAAA;EACA,sBAAA;EACA,gBAAA;EACA,WAAA;EACA,kCAAA;ElBytED;AkBttED;EACE,uBAAA;EACA,iBAAA;EACA,oBAAA;EACA,mBAAA;ElBwtED;AkB7sED;Eb4BE,gCAAA;EACG,6BAAA;EACK,wBAAA;ELorET;AkB7sED;;EAEE,iBAAA;EACA,oBAAA;EACA,qBAAA;ElB+sED;AkB3sED;EACE,gBAAA;ElB6sED;AkBzsED;EACE,gBAAA;EACA,aAAA;ElB2sED;AkBvsED;;EAEE,cAAA;ElBysED;AkBrsED;;;EZxEE,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENixED;AkBrsED;EACE,gBAAA;EACA,kBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;ElBusED;AkB7qED;EACE,gBAAA;EACA,aAAA;EACA,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,2BAAA;EACA,wBAAA;EACA,2BAAA;EACA,oBAAA;EbzDA,0DAAA;EACQ,kDAAA;EAsHR,wFAAA;EACK,2EAAA;EACG,wEAAA;ELonET;AmB7vEC;EACE,uBAAA;EACA,YAAA;EdcF,wFAAA;EACQ,gFAAA;ELkvET;AKltEC;EAAgC,gBAAA;EACA,YAAA;ELqtEjC;AKptEC;EAAgC,gBAAA;ELutEjC;AKttEC;EAAgC,gBAAA;ELytEjC;AkBrrEC;;;EAGE,qBAAA;EACA,2BAAA;EACA,YAAA;ElBurEH;AkBnrEC;EACE,cAAA;ElBqrEH;AkBzqED;EACE,0BAAA;ElB2qED;AkB/pED;;;;EAIE,mBAAA;EAEA,4BAAA;ElBgqED;AkB9pEC;;;;EACE,mBAAA;ElBmqEH;AkBjqEC;;;;EACE,mBAAA;ElBsqEH;AkB5pED;EACE,qBAAA;ElB8pED;AkBtpED;;EAEE,oBAAA;EACA,gBAAA;EACA,kBAAA;EACA,kBAAA;EACA,qBAAA;ElBwpED;AkB9pED;;EASI,oBAAA;EACA,kBAAA;EACA,qBAAA;EACA,iBAAA;ElBypEH;AkBtpED;;;;EAIE,oBAAA;EACA,oBAAA;EACA,oBAAA;ElBwpED;AkBrpED;;EAEE,kBAAA;ElBupED;AkBnpED;;EAEE,uBAAA;EACA,oBAAA;EACA,kBAAA;EACA,wBAAA;EACA,qBAAA;EACA,iBAAA;ElBqpED;AkBnpED;;EAEE,eAAA;EACA,mBAAA;ElBqpED;AkB5oEC;;;;;;EAGE,qBAAA;ElBipEH;AkB3oEC;;;;EAEE,qBAAA;ElB+oEH;AkBzoEC;;;;EAGI,qBAAA;ElB4oEL;AkBjoED;EAEE,kBAAA;EACA,qBAAA;EAEA,kBAAA;ElBioED;AkB/nEC;;EAEE,iBAAA;EACA,kBAAA;ElBioEH;AkBvnED;;ECnPE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;EnB82ED;AmB52EC;EACE,cAAA;EACA,mBAAA;EnB82EH;AmB32EC;;EAEE,cAAA;EnB62EH;AkBnoED;;ECvPE,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,oBAAA;EnB83ED;AmB53EC;EACE,cAAA;EACA,mBAAA;EnB83EH;AmB33EC;;EAEE,cAAA;EnB63EH;AkB1oED;EAEE,oBAAA;ElB2oED;AkB7oED;EAMI,uBAAA;ElB0oEH;AkBtoED;EACE,oBAAA;EACA,WAAA;EACA,UAAA;EACA,YAAA;EACA,gBAAA;EACA,aAAA;EACA,cAAA;EACA,mBAAA;EACA,oBAAA;ElBwoED;AkBtoED;EACE,aAAA;EACA,cAAA;EACA,mBAAA;ElBwoED;AkBtoED;EACE,aAAA;EACA,cAAA;EACA,mBAAA;ElBwoED;AkBpoED;;;;;;ECrVI,gBAAA;EnBi+EH;AkB5oED;ECjVI,uBAAA;EdmDF,0DAAA;EACQ,kDAAA;EL86ET;AmBh+EG;EACE,uBAAA;EdgDJ,2EAAA;EACQ,mEAAA;ELm7ET;AkBtpED;ECvUI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnBg+EH;AkB3pED;ECjUI,gBAAA;EnB+9EH;AkB3pED;;;;;;ECxVI,gBAAA;EnB2/EH;AkBnqED;ECpVI,uBAAA;EdmDF,0DAAA;EACQ,kDAAA;ELw8ET;AmB1/EG;EACE,uBAAA;EdgDJ,2EAAA;EACQ,mEAAA;EL68ET;AkB7qED;EC1UI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnB0/EH;AkBlrED;ECpUI,gBAAA;EnBy/EH;AkBlrED;;;;;;EC3VI,gBAAA;EnBqhFH;AkB1rED;ECvVI,uBAAA;EdmDF,0DAAA;EACQ,kDAAA;ELk+ET;AmBphFG;EACE,uBAAA;EdgDJ,2EAAA;EACQ,mEAAA;ELu+ET;AkBpsED;EC7UI,gBAAA;EACA,uBAAA;EACA,2BAAA;EnBohFH;AkBzsED;ECvUI,gBAAA;EnBmhFH;AkBtsED;EACE,QAAA;ElBwsED;AkB/rED;EACE,gBAAA;EACA,iBAAA;EACA,qBAAA;EACA,gBAAA;ElBisED;AkB9mED;EAAA;IA7DM,uBAAA;IACA,kBAAA;IACA,wBAAA;IlB+qEH;EkBpnEH;IAtDM,uBAAA;IACA,aAAA;IACA,wBAAA;IlB6qEH;EkBznEH;IAhDM,uBAAA;IACA,wBAAA;IlB4qEH;EkB7nEH;;;IA1CQ,aAAA;IlB4qEL;EkBloEH;IApCM,aAAA;IlByqEH;EkBroEH;IAhCM,kBAAA;IACA,wBAAA;IlBwqEH;EkBzoEH;;IAvBM,uBAAA;IACA,eAAA;IACA,kBAAA;IACA,wBAAA;IlBoqEH;EkBhpEH;;IAjBQ,iBAAA;IlBqqEL;EkBppEH;;IAZM,oBAAA;IACA,gBAAA;IlBoqEH;EkBzpEH;IAHM,QAAA;IlB+pEH;EACF;AkBrpED;;;;EASI,eAAA;EACA,kBAAA;EACA,kBAAA;ElBkpEH;AkB7pED;;EAiBI,kBAAA;ElBgpEH;AkBjqED;EJxcE,oBAAA;EACA,qBAAA;Ed4mFD;AkBloEC;EAAA;IANI,mBAAA;IACA,kBAAA;IACA,kBAAA;IlB4oEH;EACF;AkB5qED;EAwCI,QAAA;EACA,aAAA;ElBuoEH;AkB1nEG;EAAA;IAHI,qBAAA;IlBioEL;EACF;AkBrnEG;EAAA;IAHI,kBAAA;IlB4nEL;EACF;AoBzoFD;EACE,uBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,wBAAA;EACA,iBAAA;EACA,wBAAA;EACA,+BAAA;EACA,qBAAA;EC4BA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,oBAAA;EhB2KA,2BAAA;EACG,wBAAA;EACC,uBAAA;EACI,mBAAA;ELs8ET;AoB5oFG;;;EdpBF,sBAAA;EAEA,4CAAA;EACA,sBAAA;ENoqFD;AoB9oFC;;EAEE,gBAAA;EACA,uBAAA;EpBgpFH;AoB7oFC;;EAEE,YAAA;EACA,wBAAA;Ef8BF,0DAAA;EACQ,kDAAA;ELknFT;AoB7oFC;;;EAGE,qBAAA;EACA,sBAAA;EE3CF,eAAA;EAGA,2BAAA;EjB8DA,0BAAA;EACQ,kBAAA;EL4nFT;AoBzoFD;EClDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB8rFD;AqB5rFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB8rFP;AqB5rFC;;;EAGE,wBAAA;ErB8rFH;AqBzrFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBqsFT;AoB9qFD;EClBI,gBAAA;EACA,2BAAA;ErBmsFH;AoB/qFD;ECrDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBuuFD;AqBruFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBuuFP;AqBruFC;;;EAGE,wBAAA;ErBuuFH;AqBluFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErB8uFT;AoBptFD;ECrBI,gBAAA;EACA,2BAAA;ErB4uFH;AoBptFD;ECzDE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBgxFD;AqB9wFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBgxFP;AqB9wFC;;;EAGE,wBAAA;ErBgxFH;AqB3wFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBuxFT;AoBzvFD;ECzBI,gBAAA;EACA,2BAAA;ErBqxFH;AoBzvFD;EC7DE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErByzFD;AqBvzFC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErByzFP;AqBvzFC;;;EAGE,wBAAA;ErByzFH;AqBpzFG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBg0FT;AoB9xFD;EC7BI,gBAAA;EACA,2BAAA;ErB8zFH;AoB9xFD;ECjEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErBk2FD;AqBh2FC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErBk2FP;AqBh2FC;;;EAGE,wBAAA;ErBk2FH;AqB71FG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBy2FT;AoBn0FD;ECjCI,gBAAA;EACA,2BAAA;ErBu2FH;AoBn0FD;ECrEE,gBAAA;EACA,2BAAA;EACA,uBAAA;ErB24FD;AqBz4FC;;;;;EAKE,gBAAA;EACA,2BAAA;EACI,uBAAA;ErB24FP;AqBz4FC;;;EAGE,wBAAA;ErB24FH;AqBt4FG;;;;;;;;;;;;;;;EAKE,2BAAA;EACI,uBAAA;ErBk5FT;AoBx2FD;ECrCI,gBAAA;EACA,2BAAA;ErBg5FH;AoBn2FD;EACE,gBAAA;EACA,qBAAA;EACA,iBAAA;EACA,kBAAA;EpBq2FD;AoBn2FC;;;;EAIE,+BAAA;Ef1BF,0BAAA;EACQ,kBAAA;ELg4FT;AoBp2FC;;;;EAIE,2BAAA;EpBs2FH;AoBp2FC;;EAEE,gBAAA;EACA,4BAAA;EACA,+BAAA;EpBs2FH;AoBl2FG;;;;EAEE,gBAAA;EACA,uBAAA;EpBs2FL;AoB71FD;;EC9EE,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,oBAAA;ErB+6FD;AoBh2FD;;EClFE,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;ErBs7FD;AoBn2FD;;ECtFE,kBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;ErB67FD;AoBl2FD;EACE,gBAAA;EACA,aAAA;EpBo2FD;AoBh2FD;EACE,iBAAA;EpBk2FD;AoB31FC;;;EACE,aAAA;EpB+1FH;AuBh/FD;EACE,YAAA;ElBiLA,0CAAA;EACK,qCAAA;EACG,kCAAA;ELk0FT;AuBn/FC;EACE,YAAA;EvBq/FH;AuBj/FD;EACE,eAAA;EvBm/FD;AuBj/FC;EAAY,gBAAA;EvBo/Fb;AuBn/FC;EAAY,oBAAA;EvBs/Fb;AuBr/FC;EAAY,0BAAA;EvBw/Fb;AuBr/FD;EACE,oBAAA;EACA,WAAA;EACA,kBAAA;ElB+JA,uCAAA;EACK,kCAAA;EACG,+BAAA;ELy1FT;AwBhhGD;EACE,uBAAA;EACA,UAAA;EACA,WAAA;EACA,kBAAA;EACA,wBAAA;EACA,uBAAA;EACA,qCAAA;EACA,oCAAA;ExBkhGD;AwB9gGD;EACE,oBAAA;ExBghGD;AwB5gGD;EACE,YAAA;ExB8gGD;AwB1gGD;EACE,oBAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,eAAA;EACA,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,kBAAA;EACA,iBAAA;EACA,kBAAA;EACA,2BAAA;EACA,2BAAA;EACA,uCAAA;EACA,oBAAA;EnBwBA,qDAAA;EACQ,6CAAA;EmBvBR,sCAAA;EAAA,8BAAA;ExB6gGD;AwBxgGC;EACE,UAAA;EACA,YAAA;ExB0gGH;AwBniGD;ECvBE,aAAA;EACA,eAAA;EACA,kBAAA;EACA,2BAAA;EzB6jGD;AwBziGD;EAmCI,gBAAA;EACA,mBAAA;EACA,aAAA;EACA,qBAAA;EACA,yBAAA;EACA,gBAAA;EACA,qBAAA;ExBygGH;AwBngGC;;EAEE,uBAAA;EACA,gBAAA;EACA,2BAAA;ExBqgGH;AwB//FC;;;EAGE,gBAAA;EACA,uBAAA;EACA,YAAA;EACA,2BAAA;ExBigGH;AwBx/FC;;;EAGE,gBAAA;ExB0/FH;AwBr/FC;;EAEE,uBAAA;EACA,+BAAA;EACA,wBAAA;EE1GF,qEAAA;EF4GE,qBAAA;ExBu/FH;AwBl/FD;EAGI,gBAAA;ExBk/FH;AwBr/FD;EAQI,YAAA;ExBg/FH;AwBx+FD;EACE,YAAA;EACA,UAAA;ExB0+FD;AwBl+FD;EACE,SAAA;EACA,aAAA;ExBo+FD;AwBh+FD;EACE,gBAAA;EACA,mBAAA;EACA,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,qBAAA;ExBk+FD;AwB99FD;EACE,iBAAA;EACA,SAAA;EACA,UAAA;EACA,WAAA;EACA,QAAA;EACA,cAAA;ExBg+FD;AwB59FD;EACE,UAAA;EACA,YAAA;ExB89FD;AwBt9FD;;EAII,eAAA;EACA,0BAAA;EACA,aAAA;ExBs9FH;AwB59FD;;EAUI,WAAA;EACA,cAAA;EACA,oBAAA;ExBs9FH;AwBh8FD;EAZE;IAnEA,YAAA;IACA,UAAA;IxBmhGC;EwBj9FD;IAzDA,SAAA;IACA,aAAA;IxB6gGC;EACF;A2B5pGD;;EAEE,oBAAA;EACA,uBAAA;EACA,wBAAA;E3B8pGD;A2BlqGD;;EAMI,oBAAA;EACA,aAAA;E3BgqGH;A2B9pGG;;;;;;;;EAIE,YAAA;E3BoqGL;A2BlqGG;;EAEE,YAAA;E3BoqGL;A2B9pGD;;;;EAKI,mBAAA;E3B+pGH;A2B1pGD;EACE,mBAAA;E3B4pGD;A2B7pGD;;EAMI,aAAA;E3B2pGH;A2BjqGD;;;EAWI,kBAAA;E3B2pGH;A2BvpGD;EACE,kBAAA;E3BypGD;A2BrpGD;EACE,gBAAA;E3BupGD;A2BtpGC;ECrDA,+BAAA;EACG,4BAAA;E5B8sGJ;A2BrpGD;;EClDE,8BAAA;EACG,2BAAA;E5B2sGJ;A2BppGD;EACE,aAAA;E3BspGD;A2BppGD;EACE,kBAAA;E3BspGD;A2BppGD;;ECtEE,+BAAA;EACG,4BAAA;E5B8tGJ;A2BnpGD;ECpEE,8BAAA;EACG,2BAAA;E5B0tGJ;A2BlpGD;;EAEE,YAAA;E3BopGD;A2BnoGD;EACE,mBAAA;EACA,oBAAA;E3BqoGD;A2BnoGD;EACE,oBAAA;EACA,qBAAA;E3BqoGD;A2BhoGD;EtBlDE,0DAAA;EACQ,kDAAA;ELqrGT;A2BhoGC;EtBtDA,0BAAA;EACQ,kBAAA;ELyrGT;A2B7nGD;EACE,gBAAA;E3B+nGD;A2B5nGD;EACE,yBAAA;EACA,wBAAA;E3B8nGD;A2B3nGD;EACE,yBAAA;E3B6nGD;A2BtnGD;;;EAII,gBAAA;EACA,aAAA;EACA,aAAA;EACA,iBAAA;E3BunGH;A2B9nGD;EAcM,aAAA;E3BmnGL;A2BjoGD;;;;EAsBI,kBAAA;EACA,gBAAA;E3BinGH;A2B5mGC;EACE,kBAAA;E3B8mGH;A2B5mGC;EACE,8BAAA;ECvKF,+BAAA;EACC,8BAAA;E5BsxGF;A2B7mGC;EACE,gCAAA;ECnLF,4BAAA;EACC,2BAAA;E5BmyGF;A2B7mGD;EACE,kBAAA;E3B+mGD;A2B7mGD;;EClLE,+BAAA;EACC,8BAAA;E5BmyGF;A2B5mGD;EChME,4BAAA;EACC,2BAAA;E5B+yGF;A2BvmGD;EACE,gBAAA;EACA,aAAA;EACA,qBAAA;EACA,2BAAA;E3BymGD;A2B7mGD;;EAOI,aAAA;EACA,qBAAA;EACA,WAAA;E3B0mGH;A2BnnGD;EAYI,aAAA;E3B0mGH;A2BtnGD;EAgBI,YAAA;E3BymGH;A2B3lGD;;EAEE,oBAAA;EACA,aAAA;EL1OA,YAAA;EAGA,0BAAA;EtBs0GD;A6Bt0GD;EACE,oBAAA;EACA,gBAAA;EACA,2BAAA;E7Bw0GD;A6Br0GC;EACE,aAAA;EACA,iBAAA;EACA,kBAAA;E7Bu0GH;A6Bh1GD;EAeI,oBAAA;EACA,YAAA;EAKA,aAAA;EAEA,aAAA;EACA,kBAAA;E7B+zGH;A6BtzGD;;;EV0BE,cAAA;EACA,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,oBAAA;EnBiyGD;AmB/xGC;;;EACE,cAAA;EACA,mBAAA;EnBmyGH;AmBhyGC;;;;;;EAEE,cAAA;EnBsyGH;A6Bx0GD;;;EVqBE,cAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;EnBwzGD;AmBtzGC;;;EACE,cAAA;EACA,mBAAA;EnB0zGH;AmBvzGC;;;;;;EAEE,cAAA;EnB6zGH;A6Bt1GD;;;EAGE,qBAAA;E7Bw1GD;A6Bt1GC;;;EACE,kBAAA;E7B01GH;A6Bt1GD;;EAEE,WAAA;EACA,qBAAA;EACA,wBAAA;E7Bw1GD;A6Bn1GD;EACE,mBAAA;EACA,iBAAA;EACA,qBAAA;EACA,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;E7Bq1GD;A6Bl1GC;EACE,mBAAA;EACA,iBAAA;EACA,oBAAA;E7Bo1GH;A6Bl1GC;EACE,oBAAA;EACA,iBAAA;EACA,oBAAA;E7Bo1GH;A6Bx2GD;;EA0BI,eAAA;E7Bk1GH;A6B70GD;;;;;;;EDhGE,+BAAA;EACG,4BAAA;E5Bs7GJ;A6B90GD;EACE,iBAAA;E7Bg1GD;A6B90GD;;;;;;;EDpGE,8BAAA;EACG,2BAAA;E5B27GJ;A6B/0GD;EACE,gBAAA;E7Bi1GD;A6B50GD;EACE,oBAAA;EAGA,cAAA;EACA,qBAAA;E7B40GD;A6Bj1GD;EAUI,oBAAA;E7B00GH;A6Bp1GD;EAYM,mBAAA;E7B20GL;A6Bx0GG;;;EAGE,YAAA;E7B00GL;A6Br0GC;;EAGI,oBAAA;E7Bs0GL;A6Bn0GC;;EAGI,mBAAA;E7Bo0GL;A8B99GD;EACE,kBAAA;EACA,iBAAA;EACA,kBAAA;E9Bg+GD;A8Bn+GD;EAOI,oBAAA;EACA,gBAAA;E9B+9GH;A8Bv+GD;EAWM,oBAAA;EACA,gBAAA;EACA,oBAAA;E9B+9GL;A8B99GK;;EAEE,uBAAA;EACA,2BAAA;E9Bg+GP;A8B39GG;EACE,gBAAA;E9B69GL;A8B39GK;;EAEE,gBAAA;EACA,uBAAA;EACA,+BAAA;EACA,qBAAA;E9B69GP;A8Bt9GG;;;EAGE,2BAAA;EACA,uBAAA;E9Bw9GL;A8BjgHD;ELHE,aAAA;EACA,eAAA;EACA,kBAAA;EACA,2BAAA;EzBugHD;A8BvgHD;EA0DI,iBAAA;E9Bg9GH;A8Bv8GD;EACE,kCAAA;E9By8GD;A8B18GD;EAGI,aAAA;EAEA,qBAAA;E9By8GH;A8B98GD;EASM,mBAAA;EACA,yBAAA;EACA,+BAAA;EACA,4BAAA;E9Bw8GL;A8Bv8GK;EACE,uCAAA;E9By8GP;A8Bn8GK;;;EAGE,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,kCAAA;EACA,iBAAA;E9Bq8GP;A8Bh8GC;EAqDA,aAAA;EA8BA,kBAAA;E9Bi3GD;A8Bp8GC;EAwDE,aAAA;E9B+4GH;A8Bv8GC;EA0DI,oBAAA;EACA,oBAAA;E9Bg5GL;A8B38GC;EAgEE,WAAA;EACA,YAAA;E9B84GH;A8Bl4GD;EAAA;IAPM,qBAAA;IACA,WAAA;I9B64GH;E8Bv4GH;IAJQ,kBAAA;I9B84GL;EACF;A8Bx9GC;EAuFE,iBAAA;EACA,oBAAA;E9Bo4GH;A8B59GC;;;EA8FE,2BAAA;E9Bm4GH;A8Br3GD;EAAA;IATM,kCAAA;IACA,4BAAA;I9Bk4GH;E8B13GH;;;IAHM,8BAAA;I9Bk4GH;EACF;A8Bn+GD;EAEI,aAAA;E9Bo+GH;A8Bt+GD;EAMM,oBAAA;E9Bm+GL;A8Bz+GD;EASM,kBAAA;E9Bm+GL;A8B99GK;;;EAGE,gBAAA;EACA,2BAAA;E9Bg+GP;A8Bx9GD;EAEI,aAAA;E9By9GH;A8B39GD;EAIM,iBAAA;EACA,gBAAA;E9B09GL;A8B98GD;EACE,aAAA;E9Bg9GD;A8Bj9GD;EAII,aAAA;E9Bg9GH;A8Bp9GD;EAMM,oBAAA;EACA,oBAAA;E9Bi9GL;A8Bx9GD;EAYI,WAAA;EACA,YAAA;E9B+8GH;A8Bn8GD;EAAA;IAPM,qBAAA;IACA,WAAA;I9B88GH;E8Bx8GH;IAJQ,kBAAA;I9B+8GL;EACF;A8Bv8GD;EACE,kBAAA;E9By8GD;A8B18GD;EAKI,iBAAA;EACA,oBAAA;E9Bw8GH;A8B98GD;;;EAYI,2BAAA;E9Bu8GH;A8Bz7GD;EAAA;IATM,kCAAA;IACA,4BAAA;I9Bs8GH;E8B97GH;;;IAHM,8BAAA;I9Bs8GH;EACF;A8B77GD;EAEI,eAAA;E9B87GH;A8Bh8GD;EAKI,gBAAA;E9B87GH;A8Br7GD;EAEE,kBAAA;EF3OA,4BAAA;EACC,2BAAA;E5BkqHF;A+B5pHD;EACE,oBAAA;EACA,kBAAA;EACA,qBAAA;EACA,+BAAA;E/B8pHD;A+BtpHD;EAAA;IAFI,oBAAA;I/B4pHD;EACF;A+B7oHD;EAAA;IAFI,aAAA;I/BmpHD;EACF;A+BroHD;EACE,qBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mCAAA;EACA,4DAAA;EAAA,oDAAA;EAEA,mCAAA;E/BsoHD;A+BpoHC;EACE,kBAAA;E/BsoHH;A+B1mHD;EAAA;IAxBI,aAAA;IACA,eAAA;IACA,0BAAA;IAAA,kBAAA;I/BsoHD;E+BpoHC;IACE,2BAAA;IACA,yBAAA;IACA,mBAAA;IACA,8BAAA;I/BsoHH;E+BnoHC;IACE,qBAAA;I/BqoHH;E+BhoHC;;;IAGE,iBAAA;IACA,kBAAA;I/BkoHH;EACF;A+B9nHD;;EAGI,mBAAA;E/B+nHH;A+B1nHC;EAAA;;IAFI,mBAAA;I/BioHH;EACF;A+BxnHD;;;;EAII,qBAAA;EACA,oBAAA;E/B0nHH;A+BpnHC;EAAA;;;;IAHI,iBAAA;IACA,gBAAA;I/B8nHH;EACF;A+BlnHD;EACE,eAAA;EACA,uBAAA;E/BonHD;A+B/mHD;EAAA;IAFI,kBAAA;I/BqnHD;EACF;A+BjnHD;;EAEE,iBAAA;EACA,UAAA;EACA,SAAA;EACA,eAAA;E1BGA,yCAAA;EACQ,oCAAA;EAAA,iCAAA;ELinHT;A+B9mHD;EAAA;;IAFI,kBAAA;I/BqnHD;EACF;A+BnnHD;EACE,QAAA;EACA,uBAAA;E/BqnHD;A+BnnHD;EACE,WAAA;EACA,kBAAA;EACA,uBAAA;E/BqnHD;A+B/mHD;EACE,aAAA;EACA,oBAAA;EACA,iBAAA;EACA,mBAAA;EACA,cAAA;E/BinHD;A+B/mHC;;EAEE,uBAAA;E/BinHH;A+BxmHD;EALI;;IAEE,oBAAA;I/BgnHH;EACF;A+BtmHD;EACE,oBAAA;EACA,cAAA;EACA,oBAAA;EACA,mBAAA;EC3LA,iBAAA;EACA,oBAAA;ED4LA,+BAAA;EACA,wBAAA;EACA,+BAAA;EACA,oBAAA;E/BymHD;A+BrmHC;EACE,YAAA;E/BumHH;A+BrnHD;EAmBI,gBAAA;EACA,aAAA;EACA,aAAA;EACA,oBAAA;E/BqmHH;A+B3nHD;EAyBI,iBAAA;E/BqmHH;A+B/lHD;EAAA;IAFI,eAAA;I/BqmHD;EACF;A+B5lHD;EACE,qBAAA;E/B8lHD;A+B/lHD;EAII,mBAAA;EACA,sBAAA;EACA,mBAAA;E/B8lHH;A+BnkHC;EAAA;IArBI,kBAAA;IACA,aAAA;IACA,aAAA;IACA,eAAA;IACA,+BAAA;IACA,WAAA;IACA,0BAAA;IAAA,kBAAA;I/B4lHH;E+B7kHD;;IAZM,4BAAA;I/B6lHL;E+BjlHD;IATM,mBAAA;I/B6lHL;E+B5lHK;;IAEE,wBAAA;I/B8lHP;EACF;A+BxkHD;EAAA;IAfI,aAAA;IACA,WAAA;I/B2lHD;E+B7kHH;IAXM,aAAA;I/B2lHH;E+BhlHH;IATQ,mBAAA;IACA,sBAAA;I/B4lHL;E+BxlHC;IACE,qBAAA;I/B0lHH;EACF;A+BzkHD;EALE;IE9QA,wBAAA;IjCg2HC;E+BjlHD;IElRA,yBAAA;IjCs2HC;EACF;A+B5kHD;EACE,oBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mCAAA;EACA,sCAAA;E1B3OA,8FAAA;EACQ,sFAAA;E2B/DR,iBAAA;EACA,oBAAA;EhC03HD;AkBl7GD;EAAA;IA7DM,uBAAA;IACA,kBAAA;IACA,wBAAA;IlBm/GH;EkBx7GH;IAtDM,uBAAA;IACA,aAAA;IACA,wBAAA;IlBi/GH;EkB77GH;IAhDM,uBAAA;IACA,wBAAA;IlBg/GH;EkBj8GH;;;IA1CQ,aAAA;IlBg/GL;EkBt8GH;IApCM,aAAA;IlB6+GH;EkBz8GH;IAhCM,kBAAA;IACA,wBAAA;IlB4+GH;EkB78GH;;IAvBM,uBAAA;IACA,eAAA;IACA,kBAAA;IACA,wBAAA;IlBw+GH;EkBp9GH;;IAjBQ,iBAAA;IlBy+GL;EkBx9GH;;IAZM,oBAAA;IACA,gBAAA;IlBw+GH;EkB79GH;IAHM,QAAA;IlBm+GH;EACF;A+BtnHC;EAAA;IAFI,oBAAA;I/B4nHH;EACF;A+BvmHD;EAAA;IAbI,aAAA;IACA,WAAA;IACA,gBAAA;IACA,iBAAA;IACA,gBAAA;IACA,mBAAA;I1BlQF,0BAAA;IACQ,kBAAA;IL23HP;E+BtnHC;IACE,qBAAA;I/BwnHH;EACF;A+BhnHD;EACE,eAAA;EHlVA,4BAAA;EACC,2BAAA;E5Bq8HF;A+BhnHD;EH9UE,+BAAA;EACC,8BAAA;E5Bi8HF;A+B3mHD;EC5VE,iBAAA;EACA,oBAAA;EhC08HD;A+B5mHC;EC/VA,kBAAA;EACA,qBAAA;EhC88HD;A+B7mHC;EClWA,kBAAA;EACA,qBAAA;EhCk9HD;A+BvmHD;EC5WE,kBAAA;EACA,qBAAA;EhCs9HD;A+B9lHD;EAAA;IATI,aAAA;IACA,mBAAA;IACA,oBAAA;I/B2mHD;E+BxmHC;IACE,iBAAA;I/B0mHH;EACF;A+BlmHD;EACE,2BAAA;EACA,uBAAA;E/BomHD;A+BtmHD;EAKI,gBAAA;E/BomHH;A+BnmHG;;EAEE,gBAAA;EACA,+BAAA;E/BqmHL;A+B9mHD;EAcI,gBAAA;E/BmmHH;A+BjnHD;EAmBM,gBAAA;E/BimHL;A+B/lHK;;EAEE,gBAAA;EACA,+BAAA;E/BimHP;A+B7lHK;;;EAGE,gBAAA;EACA,2BAAA;E/B+lHP;A+B3lHK;;;EAGE,gBAAA;EACA,+BAAA;E/B6lHP;A+BroHD;EA8CI,uBAAA;E/B0lHH;A+BzlHG;;EAEE,2BAAA;E/B2lHL;A+B5oHD;EAoDM,2BAAA;E/B2lHL;A+B/oHD;;EA0DI,uBAAA;E/BylHH;A+BllHK;;;EAGE,2BAAA;EACA,gBAAA;E/BolHP;A+BnjHC;EAAA;IAzBQ,gBAAA;I/BglHP;E+B/kHO;;IAEE,gBAAA;IACA,+BAAA;I/BilHT;E+B7kHO;;;IAGE,gBAAA;IACA,2BAAA;I/B+kHT;E+B3kHO;;;IAGE,gBAAA;IACA,+BAAA;I/B6kHT;EACF;A+B/qHD;EA8GI,gBAAA;E/BokHH;A+BnkHG;EACE,gBAAA;E/BqkHL;A+BrrHD;EAqHI,gBAAA;E/BmkHH;A+BlkHG;;EAEE,gBAAA;E/BokHL;A+BhkHK;;;;EAEE,gBAAA;E/BokHP;A+B5jHD;EACE,2BAAA;EACA,uBAAA;E/B8jHD;A+BhkHD;EAKI,gBAAA;E/B8jHH;A+B7jHG;;EAEE,gBAAA;EACA,+BAAA;E/B+jHL;A+BxkHD;EAcI,gBAAA;E/B6jHH;A+B3kHD;EAmBM,gBAAA;E/B2jHL;A+BzjHK;;EAEE,gBAAA;EACA,+BAAA;E/B2jHP;A+BvjHK;;;EAGE,gBAAA;EACA,2BAAA;E/ByjHP;A+BrjHK;;;EAGE,gBAAA;EACA,+BAAA;E/BujHP;A+B/lHD;EA+CI,uBAAA;E/BmjHH;A+BljHG;;EAEE,2BAAA;E/BojHL;A+BtmHD;EAqDM,2BAAA;E/BojHL;A+BzmHD;;EA2DI,uBAAA;E/BkjHH;A+B5iHK;;;EAGE,2BAAA;EACA,gBAAA;E/B8iHP;A+BvgHC;EAAA;IA/BQ,uBAAA;I/B0iHP;E+B3gHD;IA5BQ,2BAAA;I/B0iHP;E+B9gHD;IAzBQ,gBAAA;I/B0iHP;E+BziHO;;IAEE,gBAAA;IACA,+BAAA;I/B2iHT;E+BviHO;;;IAGE,gBAAA;IACA,2BAAA;I/ByiHT;E+BriHO;;;IAGE,gBAAA;IACA,+BAAA;I/BuiHT;EACF;A+B/oHD;EA+GI,gBAAA;E/BmiHH;A+BliHG;EACE,gBAAA;E/BoiHL;A+BrpHD;EAsHI,gBAAA;E/BkiHH;A+BjiHG;;EAEE,gBAAA;E/BmiHL;A+B/hHK;;;;EAEE,gBAAA;E/BmiHP;AkCxqID;EACE,mBAAA;EACA,qBAAA;EACA,kBAAA;EACA,2BAAA;EACA,oBAAA;ElC0qID;AkC/qID;EAQI,uBAAA;ElC0qIH;AkClrID;EAWM,mBAAA;EACA,gBAAA;EACA,gBAAA;ElC0qIL;AkCvrID;EAkBI,gBAAA;ElCwqIH;AmC5rID;EACE,uBAAA;EACA,iBAAA;EACA,gBAAA;EACA,oBAAA;EnC8rID;AmClsID;EAOI,iBAAA;EnC8rIH;AmCrsID;;EAUM,oBAAA;EACA,aAAA;EACA,mBAAA;EACA,yBAAA;EACA,uBAAA;EACA,gBAAA;EACA,2BAAA;EACA,2BAAA;EACA,mBAAA;EnC+rIL;AmC7rIG;;EAGI,gBAAA;EPXN,gCAAA;EACG,6BAAA;E5B0sIJ;AmC5rIG;;EPvBF,iCAAA;EACG,8BAAA;E5ButIJ;AmCvrIG;;;;EAEE,gBAAA;EACA,2BAAA;EACA,uBAAA;EnC2rIL;AmCrrIG;;;;;;EAGE,YAAA;EACA,gBAAA;EACA,2BAAA;EACA,uBAAA;EACA,iBAAA;EnC0rIL;AmChvID;;;;;;EAiEM,gBAAA;EACA,2BAAA;EACA,uBAAA;EACA,qBAAA;EnCurIL;AmC9qID;;EC1EM,oBAAA;EACA,iBAAA;EpC4vIL;AoC1vIG;;ERMF,gCAAA;EACG,6BAAA;E5BwvIJ;AoCzvIG;;ERRF,iCAAA;EACG,8BAAA;E5BqwIJ;AmCxrID;;EC/EM,mBAAA;EACA,iBAAA;EpC2wIL;AoCzwIG;;ERMF,gCAAA;EACG,6BAAA;E5BuwIJ;AoCxwIG;;ERRF,iCAAA;EACG,8BAAA;E5BoxIJ;AqCvxID;EACE,iBAAA;EACA,gBAAA;EACA,kBAAA;EACA,oBAAA;ErCyxID;AqC7xID;EAOI,iBAAA;ErCyxIH;AqChyID;;EAUM,uBAAA;EACA,mBAAA;EACA,2BAAA;EACA,2BAAA;EACA,qBAAA;ErC0xIL;AqCxyID;;EAmBM,uBAAA;EACA,2BAAA;ErCyxIL;AqC7yID;;EA2BM,cAAA;ErCsxIL;AqCjzID;;EAkCM,aAAA;ErCmxIL;AqCrzID;;;;EA2CM,gBAAA;EACA,2BAAA;EACA,qBAAA;ErCgxIL;AsC9zID;EACE,iBAAA;EACA,yBAAA;EACA,gBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,oBAAA;EACA,qBAAA;EACA,0BAAA;EACA,sBAAA;EtCg0ID;AsC5zIG;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;EtC8zIL;AsCzzIC;EACE,eAAA;EtC2zIH;AsCvzIC;EACE,oBAAA;EACA,WAAA;EtCyzIH;AsClzID;ECtCE,2BAAA;EvC21ID;AuCx1IG;;EAEE,2BAAA;EvC01IL;AsCrzID;EC1CE,2BAAA;EvCk2ID;AuC/1IG;;EAEE,2BAAA;EvCi2IL;AsCxzID;EC9CE,2BAAA;EvCy2ID;AuCt2IG;;EAEE,2BAAA;EvCw2IL;AsC3zID;EClDE,2BAAA;EvCg3ID;AuC72IG;;EAEE,2BAAA;EvC+2IL;AsC9zID;ECtDE,2BAAA;EvCu3ID;AuCp3IG;;EAEE,2BAAA;EvCs3IL;AsCj0ID;EC1DE,2BAAA;EvC83ID;AuC33IG;;EAEE,2BAAA;EvC63IL;AwC/3ID;EACE,uBAAA;EACA,iBAAA;EACA,kBAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,0BAAA;EACA,qBAAA;EACA,oBAAA;EACA,2BAAA;EACA,qBAAA;ExCi4ID;AwC93IC;EACE,eAAA;ExCg4IH;AwC53IC;EACE,oBAAA;EACA,WAAA;ExC83IH;AwC53IC;EACE,QAAA;EACA,kBAAA;ExC83IH;AwCz3IG;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;ExC23IL;AwCt3IC;;EAEE,gBAAA;EACA,2BAAA;ExCw3IH;AwCt3IC;EACE,kBAAA;ExCw3IH;AyCv6ID;EACE,eAAA;EACA,qBAAA;EACA,gBAAA;EACA,2BAAA;EzCy6ID;AyC76ID;;EAQI,gBAAA;EzCy6IH;AyCj7ID;EAWI,qBAAA;EACA,iBAAA;EACA,kBAAA;EzCy6IH;AyCt7ID;EAiBI,2BAAA;EzCw6IH;AyCr6IC;EACE,oBAAA;EzCu6IH;AyC57ID;EAyBI,iBAAA;EzCs6IH;AyCr5ID;EAAA;IAbI,mBAAA;IACA,sBAAA;IzCs6ID;EyCp6IC;IACE,oBAAA;IACA,qBAAA;IzCs6IH;EyC95IH;;IAHM,iBAAA;IzCq6IH;EACF;A0C58ID;EACE,gBAAA;EACA,cAAA;EACA,qBAAA;EACA,yBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;ErC8KA,0CAAA;EACK,qCAAA;EACG,kCAAA;ELiyIT;A0Cx9ID;;EAaI,mBAAA;EACA,oBAAA;E1C+8IH;A0C38IC;;;EAGE,uBAAA;E1C68IH;A0Cl+ID;EA0BI,cAAA;EACA,gBAAA;E1C28IH;A2Cp+ID;EACE,eAAA;EACA,qBAAA;EACA,+BAAA;EACA,oBAAA;E3Cs+ID;A2C1+ID;EAQI,eAAA;EAEA,gBAAA;E3Co+IH;A2C9+ID;EAcI,mBAAA;E3Cm+IH;A2Cj/ID;;EAoBI,kBAAA;E3Ci+IH;A2Cr/ID;EAuBI,iBAAA;E3Ci+IH;A2Cz9ID;;EAEE,qBAAA;E3C29ID;A2C79ID;;EAMI,oBAAA;EACA,WAAA;EACA,cAAA;EACA,gBAAA;E3C29IH;A2Cn9ID;ECrDE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5C2gJD;A2Cx9ID;EChDI,2BAAA;E5C2gJH;A2C39ID;EC7CI,gBAAA;E5C2gJH;A2C39ID;ECxDE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5CshJD;A2Ch+ID;ECnDI,2BAAA;E5CshJH;A2Cn+ID;EChDI,gBAAA;E5CshJH;A2Cn+ID;EC3DE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5CiiJD;A2Cx+ID;ECtDI,2BAAA;E5CiiJH;A2C3+ID;ECnDI,gBAAA;E5CiiJH;A2C3+ID;EC9DE,2BAAA;EACA,uBAAA;EACA,gBAAA;E5C4iJD;A2Ch/ID;ECzDI,2BAAA;E5C4iJH;A2Cn/ID;ECtDI,gBAAA;E5C4iJH;A6C9iJD;EACE;IAAQ,6BAAA;I7CijJP;E6ChjJD;IAAQ,0BAAA;I7CmjJP;EACF;A6ChjJD;EACE;IAAQ,6BAAA;I7CmjJP;E6CljJD;IAAQ,0BAAA;I7CqjJP;EACF;A6CxjJD;EACE;IAAQ,6BAAA;I7CmjJP;E6CljJD;IAAQ,0BAAA;I7CqjJP;EACF;A6C7iJD;EACE,kBAAA;EACA,cAAA;EACA,qBAAA;EACA,2BAAA;EACA,oBAAA;ExCqCA,wDAAA;EACQ,gDAAA;EL2gJT;A6C5iJD;EACE,aAAA;EACA,WAAA;EACA,cAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2BAAA;ExCwBA,wDAAA;EACQ,gDAAA;EAsHR,qCAAA;EACK,gCAAA;EACG,6BAAA;ELk6IT;A6CziJD;;ECAI,+MAAA;EACA,0MAAA;EACA,uMAAA;EDCF,oCAAA;EAAA,4BAAA;E7C6iJD;A6CtiJD;;ExC7CE,4DAAA;EACK,uDAAA;EACG,oDAAA;ELulJT;A6CriJC;;EAEE,iBAAA;E7CuiJH;A6CpiJC;EACE,gBAAA;EACA,iBAAA;EACA,+BAAA;EACA,wBAAA;EACA,0BAAA;EAAA,kBAAA;E7CsiJH;A6C7hJD;EEvFE,2BAAA;E/CunJD;A+CpnJC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9CukJH;A6CjiJD;EE3FE,2BAAA;E/C+nJD;A+C5nJC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9C+kJH;A6CriJD;EE/FE,2BAAA;E/CuoJD;A+CpoJC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9CulJH;A6CziJD;EEnGE,2BAAA;E/C+oJD;A+C5oJC;EDgDE,+MAAA;EACA,0MAAA;EACA,uMAAA;E9C+lJH;AgD9oJD;;EAEE,kBAAA;EACA,SAAA;EhDgpJD;AgD5oJD;;EAEE,kBAAA;EhD8oJD;AgD5oJD;EACE,eAAA;EhD8oJD;AgD1oJD;EACE,gBAAA;EhD4oJD;AgDxoJD;EACE,iBAAA;EhD0oJD;AgDnoJD;EAEI,oBAAA;EhDooJH;AgDtoJD;EAKI,mBAAA;EhDooJH;AgD3nJD;EACE,iBAAA;EACA,kBAAA;EhD6nJD;AiD1qJD;EAEE,qBAAA;EACA,iBAAA;EjD2qJD;AiDnqJD;EACE,oBAAA;EACA,gBAAA;EACA,oBAAA;EAEA,qBAAA;EACA,2BAAA;EACA,2BAAA;EjDoqJD;AiDjqJC;ErB3BA,8BAAA;EACC,6BAAA;E5B+rJF;AiDlqJC;EACE,kBAAA;ErBvBF,iCAAA;EACC,gCAAA;E5B4rJF;AiDprJD;EAoBI,cAAA;EjDmqJH;AiDvrJD;EAuBI,mBAAA;EjDmqJH;AiDzpJD;EACE,gBAAA;EjD2pJD;AiD5pJD;EAII,gBAAA;EjD2pJH;AiDvpJC;;EAEE,uBAAA;EACA,gBAAA;EACA,2BAAA;EjDypJH;AiDnpJC;;;EAGE,2BAAA;EACA,gBAAA;EjDqpJH;AiDzpJC;;;EAQI,gBAAA;EjDspJL;AiD9pJC;;;EAWI,gBAAA;EjDwpJL;AiDnpJC;;;EAGE,YAAA;EACA,gBAAA;EACA,2BAAA;EACA,uBAAA;EjDqpJH;AiD3pJC;;;;;;;;;EAYI,gBAAA;EjD0pJL;AiDtqJC;;;EAeI,gBAAA;EjD4pJL;AkD/vJC;EACE,gBAAA;EACA,2BAAA;ElDiwJH;AkD/vJG;EACE,gBAAA;ElDiwJL;AkDlwJG;EAII,gBAAA;ElDiwJP;AkD9vJK;;EAEE,gBAAA;EACA,2BAAA;ElDgwJP;AkD9vJK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDgwJP;AkDrxJC;EACE,gBAAA;EACA,2BAAA;ElDuxJH;AkDrxJG;EACE,gBAAA;ElDuxJL;AkDxxJG;EAII,gBAAA;ElDuxJP;AkDpxJK;;EAEE,gBAAA;EACA,2BAAA;ElDsxJP;AkDpxJK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDsxJP;AkD3yJC;EACE,gBAAA;EACA,2BAAA;ElD6yJH;AkD3yJG;EACE,gBAAA;ElD6yJL;AkD9yJG;EAII,gBAAA;ElD6yJP;AkD1yJK;;EAEE,gBAAA;EACA,2BAAA;ElD4yJP;AkD1yJK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElD4yJP;AkDj0JC;EACE,gBAAA;EACA,2BAAA;ElDm0JH;AkDj0JG;EACE,gBAAA;ElDm0JL;AkDp0JG;EAII,gBAAA;ElDm0JP;AkDh0JK;;EAEE,gBAAA;EACA,2BAAA;ElDk0JP;AkDh0JK;;;EAGE,aAAA;EACA,2BAAA;EACA,uBAAA;ElDk0JP;AiD/tJD;EACE,eAAA;EACA,oBAAA;EjDiuJD;AiD/tJD;EACE,kBAAA;EACA,kBAAA;EjDiuJD;AmD51JD;EACE,qBAAA;EACA,2BAAA;EACA,+BAAA;EACA,oBAAA;E9C0DA,mDAAA;EACQ,2CAAA;ELqyJT;AmD31JD;EACE,eAAA;EnD61JD;AmDx1JD;EACE,oBAAA;EACA,sCAAA;EvBpBA,8BAAA;EACC,6BAAA;E5B+2JF;AmD91JD;EAMI,gBAAA;EnD21JH;AmDt1JD;EACE,eAAA;EACA,kBAAA;EACA,iBAAA;EACA,gBAAA;EnDw1JD;AmD51JD;EAOI,gBAAA;EnDw1JH;AmDn1JD;EACE,oBAAA;EACA,2BAAA;EACA,+BAAA;EvBpCA,iCAAA;EACC,gCAAA;E5B03JF;AmD70JD;EAEI,kBAAA;EnD80JH;AmDh1JD;EAKM,qBAAA;EACA,kBAAA;EnD80JL;AmD10JG;EAEI,eAAA;EvBlEN,8BAAA;EACC,6BAAA;E5B84JF;AmDx0JG;EAEI,kBAAA;EvBjEN,iCAAA;EACC,gCAAA;E5B24JF;AmDp0JD;EAEI,qBAAA;EnDq0JH;AmDl0JD;EACE,qBAAA;EnDo0JD;AmD5zJD;;;EAII,kBAAA;EnD6zJH;AmDj0JD;;EvB9FE,8BAAA;EACC,6BAAA;E5Bm6JF;AmDt0JD;;;;;;;;EAgBU,6BAAA;EnDg0JT;AmDh1JD;;;;;;;;EAoBU,8BAAA;EnDs0JT;AmD11JD;;EvBtFE,iCAAA;EACC,gCAAA;E5Bo7JF;AmD/1JD;;;;;;;;EAmCU,gCAAA;EnDs0JT;AmDz2JD;;;;;;;;EAuCU,iCAAA;EnD40JT;AmDn3JD;;EA8CI,+BAAA;EnDy0JH;AmDv3JD;;EAkDI,eAAA;EnDy0JH;AmD33JD;;EAsDI,WAAA;EnDy0JH;AmD/3JD;;;;;;;;;;;;EA6DU,gBAAA;EnDg1JT;AmD74JD;;;;;;;;;;;;EAiEU,iBAAA;EnD01JT;AmD35JD;;;;;;;;EA0EU,kBAAA;EnD21JT;AmDr6JD;;;;;;;;EAmFU,kBAAA;EnD41JT;AmD/6JD;EAyFI,WAAA;EACA,kBAAA;EnDy1JH;AmD/0JD;EACE,qBAAA;EnDi1JD;AmDl1JD;EAKI,kBAAA;EACA,oBAAA;EnDg1JH;AmDt1JD;EAQM,iBAAA;EnDi1JL;AmDz1JD;EAaI,kBAAA;EnD+0JH;AmD51JD;EAeM,+BAAA;EnDg1JL;AmD/1JD;EAmBI,eAAA;EnD+0JH;AmDl2JD;EAqBM,kCAAA;EnDg1JL;AmDz0JD;EC9NE,uBAAA;EpD0iKD;AoDxiKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpD0iKH;AoD7iKC;EAMI,2BAAA;EpD0iKL;AoDhjKC;EASI,gBAAA;EACA,2BAAA;EpD0iKL;AoDviKC;EAEI,8BAAA;EpDwiKL;AmDx1JD;ECjOE,uBAAA;EpD4jKD;AoD1jKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpD4jKH;AoD/jKC;EAMI,2BAAA;EpD4jKL;AoDlkKC;EASI,gBAAA;EACA,2BAAA;EpD4jKL;AoDzjKC;EAEI,8BAAA;EpD0jKL;AmDv2JD;ECpOE,uBAAA;EpD8kKD;AoD5kKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpD8kKH;AoDjlKC;EAMI,2BAAA;EpD8kKL;AoDplKC;EASI,gBAAA;EACA,2BAAA;EpD8kKL;AoD3kKC;EAEI,8BAAA;EpD4kKL;AmDt3JD;ECvOE,uBAAA;EpDgmKD;AoD9lKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDgmKH;AoDnmKC;EAMI,2BAAA;EpDgmKL;AoDtmKC;EASI,gBAAA;EACA,2BAAA;EpDgmKL;AoD7lKC;EAEI,8BAAA;EpD8lKL;AmDr4JD;EC1OE,uBAAA;EpDknKD;AoDhnKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDknKH;AoDrnKC;EAMI,2BAAA;EpDknKL;AoDxnKC;EASI,gBAAA;EACA,2BAAA;EpDknKL;AoD/mKC;EAEI,8BAAA;EpDgnKL;AmDp5JD;EC7OE,uBAAA;EpDooKD;AoDloKC;EACE,gBAAA;EACA,2BAAA;EACA,uBAAA;EpDooKH;AoDvoKC;EAMI,2BAAA;EpDooKL;AoD1oKC;EASI,gBAAA;EACA,2BAAA;EpDooKL;AoDjoKC;EAEI,8BAAA;EpDkoKL;AqDlpKD;EACE,oBAAA;EACA,gBAAA;EACA,WAAA;EACA,YAAA;EACA,kBAAA;ErDopKD;AqDzpKD;;;;EAWI,oBAAA;EACA,QAAA;EACA,SAAA;EACA,WAAA;EACA,cAAA;EACA,aAAA;EACA,WAAA;ErDopKH;AqDhpKC;EACE,wBAAA;ErDkpKH;AqD9oKC;EACE,qBAAA;ErDgpKH;AsDzqKD;EACE,kBAAA;EACA,eAAA;EACA,qBAAA;EACA,2BAAA;EACA,2BAAA;EACA,oBAAA;EjDwDA,yDAAA;EACQ,iDAAA;ELonKT;AsDnrKD;EASI,oBAAA;EACA,mCAAA;EtD6qKH;AsDxqKD;EACE,eAAA;EACA,oBAAA;EtD0qKD;AsDxqKD;EACE,cAAA;EACA,oBAAA;EtD0qKD;AuDhsKD;EACE,cAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,gBAAA;EACA,8BAAA;EjCRA,cAAA;EAGA,2BAAA;EtBysKD;AuDjsKC;;EAEE,gBAAA;EACA,uBAAA;EACA,iBAAA;EjCfF,cAAA;EAGA,2BAAA;EtBitKD;AuD9rKC;EACE,YAAA;EACA,iBAAA;EACA,yBAAA;EACA,WAAA;EACA,0BAAA;EvDgsKH;AwDptKD;EACE,kBAAA;ExDstKD;AwDltKD;EACE,eAAA;EACA,kBAAA;EACA,iBAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,mCAAA;EAIA,YAAA;ExDitKD;AwD9sKC;EnDkHA,4CAAA;EACQ,uCAAA;EAAA,oCAAA;EA8DR,qDAAA;EAEK,2CAAA;EACG,qCAAA;ELkiKT;AwDltKC;EnD8GA,yCAAA;EACQ,oCAAA;EAAA,iCAAA;ELumKT;AwDptKD;EACE,oBAAA;EACA,kBAAA;ExDstKD;AwDltKD;EACE,oBAAA;EACA,aAAA;EACA,cAAA;ExDotKD;AwDhtKD;EACE,oBAAA;EACA,2BAAA;EACA,2BAAA;EACA,sCAAA;EACA,oBAAA;EnDaA,kDAAA;EACQ,0CAAA;EmDZR,sCAAA;EAAA,8BAAA;EAEA,YAAA;ExDktKD;AwD9sKD;EACE,iBAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EACA,SAAA;EACA,eAAA;EACA,2BAAA;ExDgtKD;AwD9sKC;ElCrEA,YAAA;EAGA,0BAAA;EtBoxKD;AwDjtKC;ElCtEA,cAAA;EAGA,2BAAA;EtBwxKD;AwDhtKD;EACE,eAAA;EACA,kCAAA;EACA,2BAAA;ExDktKD;AwD/sKD;EACE,kBAAA;ExDitKD;AwD7sKD;EACE,WAAA;EACA,yBAAA;ExD+sKD;AwD1sKD;EACE,oBAAA;EACA,eAAA;ExD4sKD;AwDxsKD;EACE,eAAA;EACA,mBAAA;EACA,+BAAA;ExD0sKD;AwD7sKD;EAQI,kBAAA;EACA,kBAAA;ExDwsKH;AwDjtKD;EAaI,mBAAA;ExDusKH;AwDptKD;EAiBI,gBAAA;ExDssKH;AwDjsKD;EACE,oBAAA;EACA,cAAA;EACA,aAAA;EACA,cAAA;EACA,kBAAA;ExDmsKD;AwDjrKD;EAZE;IACE,cAAA;IACA,mBAAA;IxDgsKD;EwD9rKD;InDvEA,mDAAA;IACQ,2CAAA;ILwwKP;EwD7rKD;IAAY,cAAA;IxDgsKX;EACF;AwD3rKD;EAFE;IAAY,cAAA;IxDisKX;EACF;AyDh1KD;EACE,oBAAA;EACA,eAAA;EACA,gBAAA;EACA,qBAAA;EACA,iBAAA;EACA,kBAAA;EnCTA,YAAA;EAGA,0BAAA;EtB01KD;AyDj1KC;EnCZA,cAAA;EAGA,2BAAA;EtB81KD;AyDp1KC;EAAW,kBAAA;EAAmB,gBAAA;EzDw1K/B;AyDv1KC;EAAW,kBAAA;EAAmB,gBAAA;EzD21K/B;AyD11KC;EAAW,iBAAA;EAAmB,gBAAA;EzD81K/B;AyD71KC;EAAW,mBAAA;EAAmB,gBAAA;EzDi2K/B;AyD71KD;EACE,kBAAA;EACA,kBAAA;EACA,gBAAA;EACA,oBAAA;EACA,uBAAA;EACA,2BAAA;EACA,oBAAA;EzD+1KD;AyD31KD;EACE,oBAAA;EACA,UAAA;EACA,WAAA;EACA,2BAAA;EACA,qBAAA;EzD61KD;AyD11KC;EACE,WAAA;EACA,WAAA;EACA,mBAAA;EACA,yBAAA;EACA,2BAAA;EzD41KH;AyD11KC;EACE,WAAA;EACA,WAAA;EACA,yBAAA;EACA,2BAAA;EzD41KH;AyD11KC;EACE,WAAA;EACA,YAAA;EACA,yBAAA;EACA,2BAAA;EzD41KH;AyD11KC;EACE,UAAA;EACA,SAAA;EACA,kBAAA;EACA,6BAAA;EACA,6BAAA;EzD41KH;AyD11KC;EACE,UAAA;EACA,UAAA;EACA,kBAAA;EACA,6BAAA;EACA,4BAAA;EzD41KH;AyD11KC;EACE,QAAA;EACA,WAAA;EACA,mBAAA;EACA,yBAAA;EACA,8BAAA;EzD41KH;AyD11KC;EACE,QAAA;EACA,WAAA;EACA,yBAAA;EACA,8BAAA;EzD41KH;AyD11KC;EACE,QAAA;EACA,YAAA;EACA,yBAAA;EACA,8BAAA;EzD41KH;A0Dn7KD;EACE,oBAAA;EACA,QAAA;EACA,SAAA;EACA,eAAA;EACA,eAAA;EACA,kBAAA;EACA,cAAA;EACA,kBAAA;EACA,2BAAA;EACA,sCAAA;EAAA,8BAAA;EACA,2BAAA;EACA,sCAAA;EACA,oBAAA;ErDkDA,mDAAA;EACQ,2CAAA;EqD/CR,qBAAA;E1Do7KD;A0Dj7KC;EAAY,mBAAA;E1Do7Kb;A0Dn7KC;EAAY,mBAAA;E1Ds7Kb;A0Dr7KC;EAAY,kBAAA;E1Dw7Kb;A0Dv7KC;EAAY,oBAAA;E1D07Kb;A0Dv7KD;EACE,WAAA;EACA,mBAAA;EACA,iBAAA;EACA,qBAAA;EACA,mBAAA;EACA,2BAAA;EACA,kCAAA;EACA,4BAAA;E1Dy7KD;A0Dt7KD;EACE,mBAAA;E1Dw7KD;A0Dh7KC;;EAEE,oBAAA;EACA,gBAAA;EACA,UAAA;EACA,WAAA;EACA,2BAAA;EACA,qBAAA;E1Dk7KH;A0D/6KD;EACE,oBAAA;E1Di7KD;A0D/6KD;EACE,oBAAA;EACA,aAAA;E1Di7KD;A0D76KC;EACE,WAAA;EACA,oBAAA;EACA,wBAAA;EACA,2BAAA;EACA,uCAAA;EACA,eAAA;E1D+6KH;A0D96KG;EACE,cAAA;EACA,aAAA;EACA,oBAAA;EACA,wBAAA;EACA,2BAAA;E1Dg7KL;A0D76KC;EACE,UAAA;EACA,aAAA;EACA,mBAAA;EACA,sBAAA;EACA,6BAAA;EACA,yCAAA;E1D+6KH;A0D96KG;EACE,cAAA;EACA,WAAA;EACA,eAAA;EACA,sBAAA;EACA,6BAAA;E1Dg7KL;A0D76KC;EACE,WAAA;EACA,oBAAA;EACA,qBAAA;EACA,8BAAA;EACA,0CAAA;EACA,YAAA;E1D+6KH;A0D96KG;EACE,cAAA;EACA,UAAA;EACA,oBAAA;EACA,qBAAA;EACA,8BAAA;E1Dg7KL;A0D56KC;EACE,UAAA;EACA,cAAA;EACA,mBAAA;EACA,uBAAA;EACA,4BAAA;EACA,wCAAA;E1D86KH;A0D76KG;EACE,cAAA;EACA,YAAA;EACA,uBAAA;EACA,4BAAA;EACA,eAAA;E1D+6KL;A2DziLD;EACE,oBAAA;E3D2iLD;A2DxiLD;EACE,oBAAA;EACA,kBAAA;EACA,aAAA;E3D0iLD;A2D7iLD;EAMI,eAAA;EACA,oBAAA;EtD0KF,2CAAA;EACK,sCAAA;EACG,mCAAA;ELi4KT;A2DpjLD;;EAcM,gBAAA;E3D0iLL;A2DxjLD;;;EAqBI,gBAAA;E3DwiLH;A2D7jLD;EAyBI,SAAA;E3DuiLH;A2DhkLD;;EA8BI,oBAAA;EACA,QAAA;EACA,aAAA;E3DsiLH;A2DtkLD;EAoCI,YAAA;E3DqiLH;A2DzkLD;EAuCI,aAAA;E3DqiLH;A2D5kLD;;EA2CI,SAAA;E3DqiLH;A2DhlLD;EA+CI,aAAA;E3DoiLH;A2DnlLD;EAkDI,YAAA;E3DoiLH;A2D5hLD;EACE,oBAAA;EACA,QAAA;EACA,SAAA;EACA,WAAA;EACA,YAAA;ErCtEA,cAAA;EAGA,2BAAA;EqCqEA,iBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2CAAA;E3D+hLD;A2D1hLC;Eb1EE,oGAAA;EACA,+FAAA;EACA,sHAAA;EAAA,gGAAA;EACA,6BAAA;EACA,wHAAA;E9CumLH;A2D9hLC;EACE,YAAA;EACA,UAAA;Eb/EA,oGAAA;EACA,+FAAA;EACA,sHAAA;EAAA,gGAAA;EACA,6BAAA;EACA,wHAAA;E9CgnLH;A2DhiLC;;EAEE,YAAA;EACA,gBAAA;EACA,uBAAA;ErC9FF,cAAA;EAGA,2BAAA;EtB+nLD;A2DjkLD;;;;EAsCI,oBAAA;EACA,UAAA;EACA,YAAA;EACA,uBAAA;E3DiiLH;A2D1kLD;;EA6CI,WAAA;EACA,oBAAA;E3DiiLH;A2D/kLD;;EAkDI,YAAA;EACA,qBAAA;E3DiiLH;A2DplLD;;EAuDI,aAAA;EACA,cAAA;EACA,mBAAA;EACA,oBAAA;E3DiiLH;A2D5hLG;EACE,kBAAA;E3D8hLL;A2D1hLG;EACE,kBAAA;E3D4hLL;A2DlhLD;EACE,oBAAA;EACA,cAAA;EACA,WAAA;EACA,aAAA;EACA,YAAA;EACA,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,oBAAA;E3DohLD;A2D7hLD;EAYI,uBAAA;EACA,aAAA;EACA,cAAA;EACA,aAAA;EACA,qBAAA;EACA,2BAAA;EACA,qBAAA;EACA,iBAAA;EAUA,2BAAA;EACA,oCAAA;E3D2gLH;A2DziLD;EAiCI,WAAA;EACA,aAAA;EACA,cAAA;EACA,2BAAA;E3D2gLH;A2DpgLD;EACE,oBAAA;EACA,WAAA;EACA,YAAA;EACA,cAAA;EACA,aAAA;EACA,mBAAA;EACA,sBAAA;EACA,gBAAA;EACA,oBAAA;EACA,2CAAA;E3DsgLD;A2DrgLC;EACE,mBAAA;E3DugLH;A2D99KD;EAhCE;;;;IAKI,aAAA;IACA,cAAA;IACA,mBAAA;IACA,iBAAA;I3DggLH;E2DxgLD;;IAYI,oBAAA;I3DggLH;E2D5gLD;;IAgBI,qBAAA;I3DggLH;E2D3/KD;IACE,WAAA;IACA,YAAA;IACA,sBAAA;I3D6/KD;E2Dz/KD;IACE,cAAA;I3D2/KD;EACF;A4D/tLC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEE,cAAA;EACA,gBAAA;E5D6vLH;A4D3vLC;;;;;;;;;;;;;;;EACE,aAAA;E5D2wLH;AiCnxLD;E4BRE,gBAAA;EACA,mBAAA;EACA,oBAAA;E7D8xLD;AiCrxLD;EACE,yBAAA;EjCuxLD;AiCrxLD;EACE,wBAAA;EjCuxLD;AiC/wLD;EACE,0BAAA;EjCixLD;AiC/wLD;EACE,2BAAA;EjCixLD;AiC/wLD;EACE,oBAAA;EjCixLD;AiC/wLD;E6BzBE,aAAA;EACA,oBAAA;EACA,mBAAA;EACA,+BAAA;EACA,WAAA;E9D2yLD;AiC7wLD;EACE,0BAAA;EACA,+BAAA;EjC+wLD;AiCxwLD;EACE,iBAAA;E5B2FA,yCAAA;EACQ,oCAAA;EAAA,iCAAA;ELgrLT;A+D9yLD;EACE,qBAAA;E/DgzLD;A+D1yLD;;;;ECdE,0BAAA;EhE8zLD;A+DzyLD;;;;;;;;;;;;EAYE,0BAAA;E/D2yLD;A+DpyLD;EAAA;IChDE,2BAAA;IhEw1LC;EgEv1LD;IAAU,gBAAA;IhE01LT;EgEz1LD;IAAU,+BAAA;IhE41LT;EgE31LD;;IACU,gCAAA;IhE81LT;EACF;A+D9yLD;EAAA;IAFI,2BAAA;I/DozLD;EACF;A+D9yLD;EAAA;IAFI,4BAAA;I/DozLD;EACF;A+D9yLD;EAAA;IAFI,kCAAA;I/DozLD;EACF;A+D7yLD;EAAA;ICrEE,2BAAA;IhEs3LC;EgEr3LD;IAAU,gBAAA;IhEw3LT;EgEv3LD;IAAU,+BAAA;IhE03LT;EgEz3LD;;IACU,gCAAA;IhE43LT;EACF;A+DvzLD;EAAA;IAFI,2BAAA;I/D6zLD;EACF;A+DvzLD;EAAA;IAFI,4BAAA;I/D6zLD;EACF;A+DvzLD;EAAA;IAFI,kCAAA;I/D6zLD;EACF;A+DtzLD;EAAA;IC1FE,2BAAA;IhEo5LC;EgEn5LD;IAAU,gBAAA;IhEs5LT;EgEr5LD;IAAU,+BAAA;IhEw5LT;EgEv5LD;;IACU,gCAAA;IhE05LT;EACF;A+Dh0LD;EAAA;IAFI,2BAAA;I/Ds0LD;EACF;A+Dh0LD;EAAA;IAFI,4BAAA;I/Ds0LD;EACF;A+Dh0LD;EAAA;IAFI,kCAAA;I/Ds0LD;EACF;A+D/zLD;EAAA;IC/GE,2BAAA;IhEk7LC;EgEj7LD;IAAU,gBAAA;IhEo7LT;EgEn7LD;IAAU,+BAAA;IhEs7LT;EgEr7LD;;IACU,gCAAA;IhEw7LT;EACF;A+Dz0LD;EAAA;IAFI,2BAAA;I/D+0LD;EACF;A+Dz0LD;EAAA;IAFI,4BAAA;I/D+0LD;EACF;A+Dz0LD;EAAA;IAFI,kCAAA;I/D+0LD;EACF;A+Dx0LD;EAAA;IC5HE,0BAAA;IhEw8LC;EACF;A+Dx0LD;EAAA;ICjIE,0BAAA;IhE68LC;EACF;A+Dx0LD;EAAA;ICtIE,0BAAA;IhEk9LC;EACF;A+Dx0LD;EAAA;IC3IE,0BAAA;IhEu9LC;EACF;A+Dr0LD;ECnJE,0BAAA;EhE29LD;A+Dl0LD;EAAA;ICjKE,2BAAA;IhEu+LC;EgEt+LD;IAAU,gBAAA;IhEy+LT;EgEx+LD;IAAU,+BAAA;IhE2+LT;EgE1+LD;;IACU,gCAAA;IhE6+LT;EACF;A+Dh1LD;EACE,0BAAA;E/Dk1LD;A+D70LD;EAAA;IAFI,2BAAA;I/Dm1LD;EACF;A+Dj1LD;EACE,0BAAA;E/Dm1LD;A+D90LD;EAAA;IAFI,4BAAA;I/Do1LD;EACF;A+Dl1LD;EACE,0BAAA;E/Do1LD;A+D/0LD;EAAA;IAFI,kCAAA;I/Dq1LD;EACF;A+D90LD;EAAA;ICpLE,0BAAA;IhEsgMC;EACF","sourcesContent":[null,"/*! normalize.css v3.0.1 | MIT License | git.io/normalize */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS text size adjust after orientation change, without disabling\n// user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background: transparent;\n}\n\n//\n// Improve readability when focused and also mouse hovered in all browsers.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n -moz-box-sizing: content-box;\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome\n// (include `-moz` to future-proof).\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n -moz-box-sizing: content-box;\n -webkit-box-sizing: content-box; // 2\n box-sizing: content-box;\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","//\n// Basic print styles\n// --------------------------------------------------\n// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css\n\n@media print {\n\n * {\n text-shadow: none !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n background: transparent !important;\n box-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links for images, or javascript/internal links\n a[href^=\"javascript:\"]:after,\n a[href^=\"#\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245\n // Once fixed, we can just straight up remove this.\n select {\n background: #fff !important;\n }\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .table {\n td,\n th {\n background-color: #fff !important;\n }\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// <a href=\"#\"><span class=\"glyphicon glyphicon-star\"></span> Star</a>\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\2a\"; } }\n.glyphicon-plus { &:before { content: \"\\2b\"; } }\n.glyphicon-euro { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: underline;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content/\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n &::-moz-placeholder { color: @color; // Firefox\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // Default\n outline: thin dotted;\n // WebKit\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n width: 100% \\9; // Force IE10 and below to size SVG images correctly\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\n// Undo browser default styling\ncite {\n font-style: normal;\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @grid-float-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Quotes\nblockquote:before,\nblockquote:after {\n content: \"\";\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: (@gutter / -2);\n margin-right: (@gutter / -2);\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: (@grid-gutter-width / 2);\n padding-right: (@grid-gutter-width / 2);\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-child(odd) {\n > td,\n > th {\n background-color: @table-bg-accent;\n }\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n > td,\n > th {\n background-color: @table-bg-hover;\n }\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n overflow-x: auto;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n -webkit-overflow-scrolling: touch;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\n// Set the height of file controls to match text inputs\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &[disabled],\n &[readonly],\n fieldset[disabled] & {\n cursor: not-allowed;\n background-color: @input-bg-disabled;\n opacity: 1; // iOS fix for unreadable disabled content\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n\n\n// Special styles for iOS temporal inputs\n//\n// In Mobile Safari, setting `display: block` on temporal inputs causes the\n// text within the input to become vertically misaligned.\n// As a workaround, we set a pixel line-height that matches the\n// given height of the input. Since this fucks up everything else, we have to\n// appropriately reset it for Internet Explorer and the size variations.\n\ninput[type=\"date\"],\ninput[type=\"time\"],\ninput[type=\"datetime-local\"],\ninput[type=\"month\"] {\n line-height: @input-height-base;\n // IE8+ misaligns the text within date inputs, so we reset\n line-height: @line-height-base ~\"\\0\";\n\n &.input-sm {\n line-height: @input-height-small;\n }\n &.input-lg {\n line-height: @input-height-large;\n }\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: 15px;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n position: relative;\n display: block;\n min-height: @line-height-computed; // clear the floating input if there is no label text\n margin-top: 10px;\n margin-bottom: 10px;\n\n label {\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n// Some special care is needed because <label>s don't inherit their parent's `cursor`.\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n &[disabled],\n &.disabled,\n fieldset[disabled] & {\n cursor: not-allowed;\n }\n}\n// These classes are used directly on <label>s\n.radio-inline,\n.checkbox-inline {\n &.disabled,\n fieldset[disabled] & {\n cursor: not-allowed;\n }\n}\n// These classes are used on elements with <label> descendants\n.radio,\n.checkbox {\n &.disabled,\n fieldset[disabled] & {\n label {\n cursor: not-allowed;\n }\n }\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n // Size it appropriately next to real form controls\n padding-top: (@padding-base-vertical + 1);\n padding-bottom: (@padding-base-vertical + 1);\n // Remove default margin from `p`\n margin-bottom: 0;\n\n &.input-lg,\n &.input-sm {\n padding-left: 0;\n padding-right: 0;\n }\n}\n\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n\n.input-sm {\n .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n.input-lg {\n .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n.has-feedback {\n // Enable absolute positioning\n position: relative;\n\n // Ensure icons don't overlap text\n .form-control {\n padding-right: (@input-height-base * 1.25);\n }\n}\n// Feedback icon (requires .glyphicon classes)\n.form-control-feedback {\n position: absolute;\n top: (@line-height-computed + 5); // Height of the `label` and its margin\n right: 0;\n z-index: 2; // Ensure icon is above input groups\n display: block;\n width: @input-height-base;\n height: @input-height-base;\n line-height: @input-height-base;\n text-align: center;\n}\n.input-lg + .form-control-feedback {\n width: @input-height-large;\n height: @input-height-large;\n line-height: @input-height-large;\n}\n.input-sm + .form-control-feedback {\n width: @input-height-small;\n height: @input-height-small;\n line-height: @input-height-small;\n}\n\n// Feedback states\n.has-success {\n .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n\n\n// Reposition feedback icon if label is hidden with \"screenreader only\" state\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n display: block; // account for any element using help-block\n margin-top: 5px;\n margin-bottom: 10px;\n color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n // Kick in the inline\n @media (min-width: @screen-sm-min) {\n // Inline-block all the things for \"inline\"\n .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // In navbar-form, allow folks to *not* use `.form-group`\n .form-control {\n display: inline-block;\n width: auto; // Prevent labels from stacking above inputs in `.form-group`\n vertical-align: middle;\n }\n\n .input-group {\n display: inline-table;\n vertical-align: middle;\n\n .input-group-addon,\n .input-group-btn,\n .form-control {\n width: auto;\n }\n }\n\n // Input groups need that 100% width though\n .input-group > .form-control {\n width: 100%;\n }\n\n .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // Remove default margin on radios/checkboxes that were used for stacking, and\n // then undo the floating of radios and checkboxes to match (which also avoids\n // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969).\n .radio,\n .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n\n label {\n padding-left: 0;\n }\n }\n .radio input[type=\"radio\"],\n .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 0;\n }\n }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n // Consistent vertical alignment of radios and checkboxes\n //\n // Labels also get some reset styles, but that is scoped to a media query below.\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n }\n // Account for padding we're adding to ensure the alignment and of help text\n // and other content below items\n .radio,\n .checkbox {\n min-height: (@line-height-computed + (@padding-base-vertical + 1));\n }\n\n // Make form groups behave like rows\n .form-group {\n .make-row();\n }\n\n // Reset spacing and right align labels, but scope to media queries so that\n // labels on narrow viewports stack the same as a default form example.\n @media (min-width: @screen-sm-min) {\n .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n }\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 0;\n right: (@grid-gutter-width / 2);\n }\n\n // Form group sizes\n //\n // Quick utility class for applying `.input-lg` and `.input-sm` styles to the\n // inputs and labels within a `.form-group`.\n .form-group-lg {\n @media (min-width: @screen-sm-min) {\n .control-label {\n padding-top: ((@padding-large-vertical * @line-height-large) + 1);\n }\n }\n .form-control {\n &:extend(.input-lg);\n }\n }\n .form-group-sm {\n @media (min-width: @screen-sm-min) {\n .control-label {\n padding-top: (@padding-small-vertical + 1);\n }\n }\n .form-control {\n &:extend(.input-sm);\n }\n }\n}\n","// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\n // Color the label and help text\n .help-block,\n .control-label,\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n color: @text-color;\n }\n // Set the border and box shadow on specific inputs to match\n .form-control {\n border-color: @border-color;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\n &:focus {\n border-color: darken(@border-color, 10%);\n @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);\n .box-shadow(@shadow);\n }\n }\n // Set validation states also for addons\n .input-group-addon {\n color: @text-color;\n border-color: @border-color;\n background-color: @background-color;\n }\n // Optional feedback icon\n .form-control-feedback {\n color: @text-color;\n }\n}\n\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `@input-border-focus` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n.form-control-focus(@color: @input-border-focus) {\n @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\n &:focus {\n border-color: @color;\n outline: 0;\n .box-shadow(~\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}\");\n }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: not-allowed;\n pointer-events: none; // Future-proof disabling of clicks\n .opacity(.65);\n .box-shadow(none);\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n cursor: pointer;\n border-radius: 0;\n\n &,\n &:active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: underline;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:hover,\n &:focus,\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &:active,\n &.active {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition(height .35s ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base solid;\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n}\n// Nuke hover/focus effects\n.dropdown-menu > .disabled > a {\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: not-allowed;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base solid;\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 1px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n &:focus {\n // Remove focus outline when dropdown JS adds it after closing the menu\n outline: 0;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n border-top-right-radius: @border-radius-base;\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n border-bottom-left-radius: @border-radius-base;\n .border-top-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `opacity`. We cannot\n// use `display: none;` or `visibility: hidden;` as that also hides the popover.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 for more.\n\n[data-toggle=\"buttons\"] > .btn > input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn > input[type=\"checkbox\"] {\n position: absolute;\n z-index: -1;\n .opacity(0);\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @border-radius-base;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n .translate3d(0, 0, 0);\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right { .pull-right(); }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n\n // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n\n // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: 0;\n }\n }\n}\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n visibility: hidden !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n .translate3d(0, 0, 0);\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: not-allowed;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: not-allowed;\n }\n }\n\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n \n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: baseline;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n .btn-xs & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n a.list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: (@font-size-base * 4.5);\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n// Account for lower percentages\n.progress-bar {\n &[aria-valuenow=\"1\"],\n &[aria-valuenow=\"2\"] {\n min-width: 30px;\n }\n\n &[aria-valuenow=\"0\"] {\n color: @gray-light;\n min-width: 30px;\n background-color: transparent;\n background-image: none;\n box-shadow: none;\n }\n}\n\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n","// Media objects\n// Source: http://stubbornella.org/content/?p=497\n// --------------------------------------------------\n\n\n// Common styles\n// -------------------------\n\n// Clear the floats\n.media,\n.media-body {\n overflow: hidden;\n zoom: 1;\n}\n\n// Proper spacing between instances of .media\n.media,\n.media .media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n\n// For images and videos, set to block\n.media-object {\n display: block;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin: 0 0 5px;\n}\n\n\n// Media image alignment\n// -------------------------\n\n.media {\n > .pull-left {\n margin-right: 10px;\n }\n > .pull-right {\n margin-left: 10px;\n }\n}\n\n\n// Media list variation\n// -------------------------\n\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n\n.list-group {\n // No need to set list-style: none; since .list-group-item is block level\n margin-bottom: 20px;\n padding-left: 0; // reset padding because ul and ol\n}\n\n\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n // Place the border on the list items and negative margin up for better styling\n margin-bottom: -1px;\n background-color: @list-group-bg;\n border: 1px solid @list-group-border;\n\n // Round the first and last items\n &:first-child {\n .border-top-radius(@list-group-border-radius);\n }\n &:last-child {\n margin-bottom: 0;\n .border-bottom-radius(@list-group-border-radius);\n }\n\n // Align badges within list items\n > .badge {\n float: right;\n }\n > .badge + .badge {\n margin-right: 5px;\n }\n}\n\n\n// Linked list items\n//\n// Use anchor elements instead of `li`s or `div`s to create linked list items.\n// Includes an extra `.active` modifier class for showing selected items.\n\na.list-group-item {\n color: @list-group-link-color;\n\n .list-group-item-heading {\n color: @list-group-link-heading-color;\n }\n\n // Hover state\n &:hover,\n &:focus {\n text-decoration: none;\n color: @list-group-link-hover-color;\n background-color: @list-group-hover-bg;\n }\n}\n\n.list-group-item {\n // Disabled state\n &.disabled,\n &.disabled:hover,\n &.disabled:focus {\n background-color: @list-group-disabled-bg;\n color: @list-group-disabled-color;\n\n // Force color to inherit for custom content\n .list-group-item-heading {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-disabled-text-color;\n }\n }\n\n // Active class on item itself, not parent\n &.active,\n &.active:hover,\n &.active:focus {\n z-index: 2; // Place active items above their siblings for proper border styling\n color: @list-group-active-color;\n background-color: @list-group-active-bg;\n border-color: @list-group-active-border;\n\n // Force color to inherit for custom content\n .list-group-item-heading,\n .list-group-item-heading > small,\n .list-group-item-heading > .small {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-active-text-color;\n }\n }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\n\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n","// List Groups\n\n.list-group-item-variant(@state; @background; @color) {\n .list-group-item-@{state} {\n color: @color;\n background-color: @background;\n\n a& {\n color: @color;\n\n .list-group-item-heading {\n color: inherit;\n }\n\n &:hover,\n &:focus {\n color: @color;\n background-color: darken(@background, 5%);\n }\n &.active,\n &.active:hover,\n &.active:focus {\n color: #fff;\n background-color: @color;\n border-color: @color;\n }\n }\n }\n}\n","//\n// Panels\n// --------------------------------------------------\n\n\n// Base class\n.panel {\n margin-bottom: @line-height-computed;\n background-color: @panel-bg;\n border: 1px solid transparent;\n border-radius: @panel-border-radius;\n .box-shadow(0 1px 1px rgba(0,0,0,.05));\n}\n\n// Panel contents\n.panel-body {\n padding: @panel-body-padding;\n &:extend(.clearfix all);\n}\n\n// Optional heading\n.panel-heading {\n padding: @panel-heading-padding;\n border-bottom: 1px solid transparent;\n .border-top-radius((@panel-border-radius - 1));\n\n > .dropdown .dropdown-toggle {\n color: inherit;\n }\n}\n\n// Within heading, strip any `h*` tag of its default margins for spacing.\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: ceil((@font-size-base * 1.125));\n color: inherit;\n\n > a {\n color: inherit;\n }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n padding: @panel-footer-padding;\n background-color: @panel-footer-bg;\n border-top: 1px solid @panel-inner-border;\n .border-bottom-radius((@panel-border-radius - 1));\n}\n\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n > .list-group {\n margin-bottom: 0;\n\n .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n }\n\n // Add border top radius for first one\n &:first-child {\n .list-group-item:first-child {\n border-top: 0;\n .border-top-radius((@panel-border-radius - 1));\n }\n }\n // Add border bottom radius for last one\n &:last-child {\n .list-group-item:last-child {\n border-bottom: 0;\n .border-bottom-radius((@panel-border-radius - 1));\n }\n }\n }\n}\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n .list-group-item:first-child {\n border-top-width: 0;\n }\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n\n// Tables in panels\n//\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\n// watch it go full width.\n\n.panel {\n > .table,\n > .table-responsive > .table,\n > .panel-collapse > .table {\n margin-bottom: 0;\n }\n // Add border top radius for first one\n > .table:first-child,\n > .table-responsive:first-child > .table:first-child {\n .border-top-radius((@panel-border-radius - 1));\n\n > thead:first-child,\n > tbody:first-child {\n > tr:first-child {\n td:first-child,\n th:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-top-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n // Add border bottom radius for last one\n > .table:last-child,\n > .table-responsive:last-child > .table:last-child {\n .border-bottom-radius((@panel-border-radius - 1));\n\n > tbody:last-child,\n > tfoot:last-child {\n > tr:last-child {\n td:first-child,\n th:first-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-bottom-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n > .panel-body + .table,\n > .panel-body + .table-responsive {\n border-top: 1px solid @table-border-color;\n }\n > .table > tbody:first-child > tr:first-child th,\n > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n }\n > .table-bordered,\n > .table-responsive > .table-bordered {\n border: 0;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n > thead,\n > tbody {\n > tr:first-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n > tbody,\n > tfoot {\n > tr:last-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n }\n > .table-responsive {\n border: 0;\n margin-bottom: 0;\n }\n}\n\n\n// Collapsable panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n margin-bottom: @line-height-computed;\n\n // Tighten up margin so it's only between panels\n .panel {\n margin-bottom: 0;\n border-radius: @panel-border-radius;\n + .panel {\n margin-top: 5px;\n }\n }\n\n .panel-heading {\n border-bottom: 0;\n + .panel-collapse > .panel-body {\n border-top: 1px solid @panel-inner-border;\n }\n }\n .panel-footer {\n border-top: 0;\n + .panel-collapse .panel-body {\n border-bottom: 1px solid @panel-inner-border;\n }\n }\n}\n\n\n// Contextual variations\n.panel-default {\n .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);\n}\n.panel-primary {\n .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\n}\n.panel-success {\n .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\n}\n.panel-info {\n .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\n}\n.panel-warning {\n .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\n}\n.panel-danger {\n .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\n}\n","// Panels\n\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n border-color: @border;\n\n & > .panel-heading {\n color: @heading-text-color;\n background-color: @heading-bg-color;\n border-color: @heading-border;\n\n + .panel-collapse > .panel-body {\n border-top-color: @border;\n }\n .badge {\n color: @heading-bg-color;\n background-color: @heading-text-color;\n }\n }\n & > .panel-footer {\n + .panel-collapse > .panel-body {\n border-bottom-color: @border;\n }\n }\n}\n","// Embeds responsive\n//\n// Credit: Nicolas Gallagher and SUIT CSS.\n\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n\n .embed-responsive-item,\n iframe,\n embed,\n object {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n }\n\n // Modifier class for 16:9 aspect ratio\n &.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n }\n\n // Modifier class for 4:3 aspect ratio\n &.embed-responsive-4by3 {\n padding-bottom: 75%;\n }\n}\n","//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: @well-bg;\n border: 1px solid @well-border;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n blockquote {\n border-color: #ddd;\n border-color: rgba(0,0,0,.15);\n }\n}\n\n// Sizes\n.well-lg {\n padding: 24px;\n border-radius: @border-radius-large;\n}\n.well-sm {\n padding: 9px;\n border-radius: @border-radius-small;\n}\n","//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n float: right;\n font-size: (@font-size-base * 1.5);\n font-weight: @close-font-weight;\n line-height: 1;\n color: @close-color;\n text-shadow: @close-text-shadow;\n .opacity(.2);\n\n &:hover,\n &:focus {\n color: @close-color;\n text-decoration: none;\n cursor: pointer;\n .opacity(.5);\n }\n\n // Additional properties for button version\n // iOS requires the button element instead of an anchor tag.\n // If you want the anchor version, it requires `href=\"#\"`.\n button& {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n }\n}\n","//\n// Modals\n// --------------------------------------------------\n\n// .modal-open - body class for killing the scroll\n// .modal - container to scroll within\n// .modal-dialog - positioning shell for the actual modal\n// .modal-content - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n overflow: hidden;\n}\n\n// Container that the modal scrolls within\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal;\n -webkit-overflow-scrolling: touch;\n\n // Prevent Chrome on Windows from adding a focus outline. For details, see\n // https://github.com/twbs/bootstrap/pull/10951.\n outline: 0;\n\n // When fading in the modal, animate it to slide down\n &.fade .modal-dialog {\n .translate3d(0, -25%, 0);\n .transition-transform(~\"0.3s ease-out\");\n }\n &.in .modal-dialog { .translate3d(0, 0, 0) }\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n\n// Actual modal\n.modal-content {\n position: relative;\n background-color: @modal-content-bg;\n border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n border: 1px solid @modal-content-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 3px 9px rgba(0,0,0,.5));\n background-clip: padding-box;\n // Remove focus outline from opened modal\n outline: 0;\n}\n\n// Modal background\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal-background;\n background-color: @modal-backdrop-bg;\n // Fade for backdrop\n &.fade { .opacity(0); }\n &.in { .opacity(@modal-backdrop-opacity); }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n padding: @modal-title-padding;\n border-bottom: 1px solid @modal-header-border-color;\n min-height: (@modal-title-padding + @modal-title-line-height);\n}\n// Close icon\n.modal-header .close {\n margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n margin: 0;\n line-height: @modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n position: relative;\n padding: @modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n padding: @modal-inner-padding;\n text-align: right; // right align buttons\n border-top: 1px solid @modal-footer-border-color;\n &:extend(.clearfix all); // clear it in case folks use .pull-* classes on buttons\n\n // Properly space out buttons\n .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n }\n // but override that for button groups\n .btn-group .btn + .btn {\n margin-left: -1px;\n }\n // and override it for block buttons as well\n .btn-block + .btn-block {\n margin-left: 0;\n }\n}\n\n// Measure scrollbar width for padding body during modal show/hide\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n\n// Scale up the modal\n@media (min-width: @screen-sm-min) {\n // Automatically set modal's width for larger viewports\n .modal-dialog {\n width: @modal-md;\n margin: 30px auto;\n }\n .modal-content {\n .box-shadow(0 5px 15px rgba(0,0,0,.5));\n }\n\n // Modal sizes\n .modal-sm { width: @modal-sm; }\n}\n\n@media (min-width: @screen-md-min) {\n .modal-lg { width: @modal-lg; }\n}\n","//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n position: absolute;\n z-index: @zindex-tooltip;\n display: block;\n visibility: visible;\n font-size: @font-size-small;\n line-height: 1.4;\n .opacity(0);\n\n &.in { .opacity(@tooltip-opacity); }\n &.top { margin-top: -3px; padding: @tooltip-arrow-width 0; }\n &.right { margin-left: 3px; padding: 0 @tooltip-arrow-width; }\n &.bottom { margin-top: 3px; padding: @tooltip-arrow-width 0; }\n &.left { margin-left: -3px; padding: 0 @tooltip-arrow-width; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n max-width: @tooltip-max-width;\n padding: 3px 8px;\n color: @tooltip-color;\n text-align: center;\n text-decoration: none;\n background-color: @tooltip-bg;\n border-radius: @border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip {\n &.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-left .tooltip-arrow {\n bottom: 0;\n left: @tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-right .tooltip-arrow {\n bottom: 0;\n right: @tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\n border-right-color: @tooltip-arrow-color;\n }\n &.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-left-color: @tooltip-arrow-color;\n }\n &.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-left .tooltip-arrow {\n top: 0;\n left: @tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-right .tooltip-arrow {\n top: 0;\n right: @tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n}\n","//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: @zindex-popover;\n display: none;\n max-width: @popover-max-width;\n padding: 1px;\n text-align: left; // Reset given new insertion method\n background-color: @popover-bg;\n background-clip: padding-box;\n border: 1px solid @popover-fallback-border-color;\n border: 1px solid @popover-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 5px 10px rgba(0,0,0,.2));\n\n // Overrides for proper insertion\n white-space: normal;\n\n // Offset the popover to account for the popover arrow\n &.top { margin-top: -@popover-arrow-width; }\n &.right { margin-left: @popover-arrow-width; }\n &.bottom { margin-top: @popover-arrow-width; }\n &.left { margin-left: -@popover-arrow-width; }\n}\n\n.popover-title {\n margin: 0; // reset heading margin\n padding: 8px 14px;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 18px;\n background-color: @popover-title-bg;\n border-bottom: 1px solid darken(@popover-title-bg, 5%);\n border-radius: (@border-radius-large - 1) (@border-radius-large - 1) 0 0;\n}\n\n.popover-content {\n padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover > .arrow {\n &,\n &:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n }\n}\n.popover > .arrow {\n border-width: @popover-arrow-outer-width;\n}\n.popover > .arrow:after {\n border-width: @popover-arrow-width;\n content: \"\";\n}\n\n.popover {\n &.top > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-top-color: @popover-arrow-outer-color;\n bottom: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n bottom: 1px;\n margin-left: -@popover-arrow-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-color;\n }\n }\n &.right > .arrow {\n top: 50%;\n left: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-right-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n left: 1px;\n bottom: -@popover-arrow-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-color;\n }\n }\n &.bottom > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-bottom-color: @popover-arrow-outer-color;\n top: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n top: 1px;\n margin-left: -@popover-arrow-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-color;\n }\n }\n\n &.left > .arrow {\n top: 50%;\n right: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-right-width: 0;\n border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-left-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: @popover-arrow-color;\n bottom: -@popover-arrow-width;\n }\n }\n\n}\n","//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators\n.carousel {\n position: relative;\n}\n\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n\n > .item {\n display: none;\n position: relative;\n .transition(.6s ease-in-out left);\n\n // Account for jankitude on images\n > img,\n > a > img {\n &:extend(.img-responsive);\n line-height: 1;\n }\n }\n\n > .active,\n > .next,\n > .prev {\n display: block;\n }\n\n > .active {\n left: 0;\n }\n\n > .next,\n > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n }\n\n > .next {\n left: 100%;\n }\n > .prev {\n left: -100%;\n }\n > .next.left,\n > .prev.right {\n left: 0;\n }\n\n > .active.left {\n left: -100%;\n }\n > .active.right {\n left: 100%;\n }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: @carousel-control-width;\n .opacity(@carousel-control-opacity);\n font-size: @carousel-control-font-size;\n color: @carousel-control-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n // We can't have this transition here because WebKit cancels the carousel\n // animation if you trip this while in the middle of another animation.\n\n // Set gradients for backgrounds\n &.left {\n #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));\n }\n &.right {\n left: auto;\n right: 0;\n #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));\n }\n\n // Hover/focus state\n &:hover,\n &:focus {\n outline: 0;\n color: @carousel-control-color;\n text-decoration: none;\n .opacity(.9);\n }\n\n // Toggles\n .icon-prev,\n .icon-next,\n .glyphicon-chevron-left,\n .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n z-index: 5;\n display: inline-block;\n }\n .icon-prev,\n .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n }\n .icon-next,\n .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n }\n .icon-prev,\n .icon-next {\n width: 20px;\n height: 20px;\n margin-top: -10px;\n font-family: serif;\n }\n\n\n .icon-prev {\n &:before {\n content: '\\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n }\n }\n .icon-next {\n &:before {\n content: '\\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n }\n }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\n\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n\n li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid @carousel-indicator-border-color;\n border-radius: 10px;\n cursor: pointer;\n\n // IE8-9 hack for event handling\n //\n // Internet Explorer 8-9 does not support clicks on elements without a set\n // `background-color`. We cannot use `filter` since that's not viewed as a\n // background color by the browser. Thus, a hack is needed.\n //\n // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n // set alpha transparency for the best results possible.\n background-color: #000 \\9; // IE8\n background-color: rgba(0,0,0,0); // IE9\n }\n .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: @carousel-indicator-active-bg;\n }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: @carousel-caption-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n & .btn {\n text-shadow: none; // No shadow for button elements in carousel-caption\n }\n}\n\n\n// Scale up controls for tablets and up\n@media screen and (min-width: @screen-sm-min) {\n\n // Scale up the controls a smidge\n .carousel-control {\n .glyphicon-chevron-left,\n .glyphicon-chevron-right,\n .icon-prev,\n .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n font-size: 30px;\n }\n .glyphicon-chevron-left,\n .icon-prev {\n margin-left: -15px;\n }\n .glyphicon-chevron-right,\n .icon-next {\n margin-right: -15px;\n }\n }\n\n // Show and left align the captions\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n\n // Move up the indicators\n .carousel-indicators {\n bottom: 20px;\n }\n}\n","// Clearfix\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n// contenteditable attribute is included anywhere else in the document.\n// Otherwise it causes space to appear at the top and bottom of elements\n// that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n// `:before` to contain the top-margins of child elements.\n//\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n\n.clearfix() {\n &:before,\n &:after {\n content: \" \"; // 1\n display: table; // 2\n }\n &:after {\n clear: both;\n }\n}\n","// Center-align a block level element\n\n.center-block() {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n","// CSS image replacement\n//\n// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n font: ~\"0/0\" a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n\n// New mixin to use as of v3.0.1\n.text-hide() {\n .hide-text();\n}\n","//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: http://getbootstrap.com/getting-started/#support-ie10-width\n// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n width: device-width;\n}\n\n\n// Visibility utilities\n// Note: Deprecated .visible-xs, .visible-sm, .visible-md, and .visible-lg as of v3.2.0\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n .responsive-invisibility();\n}\n\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n\n.visible-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-visibility();\n }\n}\n.visible-xs-block {\n @media (max-width: @screen-xs-max) {\n display: block !important;\n }\n}\n.visible-xs-inline {\n @media (max-width: @screen-xs-max) {\n display: inline !important;\n }\n}\n.visible-xs-inline-block {\n @media (max-width: @screen-xs-max) {\n display: inline-block !important;\n }\n}\n\n.visible-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-visibility();\n }\n}\n.visible-sm-block {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: block !important;\n }\n}\n.visible-sm-inline {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: inline !important;\n }\n}\n.visible-sm-inline-block {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: inline-block !important;\n }\n}\n\n.visible-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-visibility();\n }\n}\n.visible-md-block {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: block !important;\n }\n}\n.visible-md-inline {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: inline !important;\n }\n}\n.visible-md-inline-block {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: inline-block !important;\n }\n}\n\n.visible-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-visibility();\n }\n}\n.visible-lg-block {\n @media (min-width: @screen-lg-min) {\n display: block !important;\n }\n}\n.visible-lg-inline {\n @media (min-width: @screen-lg-min) {\n display: inline !important;\n }\n}\n.visible-lg-inline-block {\n @media (min-width: @screen-lg-min) {\n display: inline-block !important;\n }\n}\n\n.hidden-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-invisibility();\n }\n}\n.hidden-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-invisibility();\n }\n}\n.hidden-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-invisibility();\n }\n}\n.hidden-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-invisibility();\n }\n}\n\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n// Note: Deprecated .visible-print as of v3.2.0\n.visible-print {\n .responsive-invisibility();\n\n @media print {\n .responsive-visibility();\n }\n}\n.visible-print-block {\n display: none !important;\n\n @media print {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n\n @media print {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n\n @media print {\n display: inline-block !important;\n }\n}\n\n.hidden-print {\n @media print {\n .responsive-invisibility();\n }\n}\n","// Responsive utilities\n\n//\n// More easily include all the states for responsive-utilities.less.\n.responsive-visibility() {\n display: block !important;\n table& { display: table; }\n tr& { display: table-row !important; }\n th&,\n td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n display: none !important;\n}\n"]}
\ No newline at end of file +{"version":3,"sources":["bootstrap.css","less/normalize.less","less/print.less","less/glyphicons.less","less/scaffolding.less","less/mixins/vendor-prefixes.less","less/mixins/tab-focus.less","less/mixins/image.less","less/type.less","less/mixins/text-emphasis.less","less/mixins/background-variant.less","less/mixins/text-overflow.less","less/code.less","less/grid.less","less/mixins/grid.less","less/mixins/grid-framework.less","less/tables.less","less/mixins/table-row.less","less/forms.less","less/mixins/forms.less","less/buttons.less","less/mixins/buttons.less","less/mixins/opacity.less","less/component-animations.less","less/dropdowns.less","less/mixins/nav-divider.less","less/mixins/reset-filter.less","less/button-groups.less","less/mixins/border-radius.less","less/input-groups.less","less/navs.less","less/navbar.less","less/mixins/nav-vertical-align.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/mixins/pagination.less","less/pager.less","less/labels.less","less/mixins/labels.less","less/badges.less","less/jumbotron.less","less/thumbnails.less","less/alerts.less","less/mixins/alerts.less","less/progress-bars.less","less/mixins/gradients.less","less/mixins/progress-bar.less","less/media.less","less/list-group.less","less/mixins/list-group.less","less/panels.less","less/mixins/panels.less","less/responsive-embed.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/mixins/reset-text.less","less/popovers.less","less/carousel.less","less/mixins/clearfix.less","less/mixins/center-block.less","less/mixins/hide-text.less","less/responsive-utilities.less","less/mixins/responsive-visibility.less"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,4EAA4E;ACG5E;EACE,wBAAA;EACA,2BAAA;EACA,+BAAA;CDDD;ACQD;EACE,UAAA;CDND;ACmBD;;;;;;;;;;;;;EAaE,eAAA;CDjBD;ACyBD;;;;EAIE,sBAAA;EACA,yBAAA;CDvBD;AC+BD;EACE,cAAA;EACA,UAAA;CD7BD;ACqCD;;EAEE,cAAA;CDnCD;AC6CD;EACE,8BAAA;CD3CD;ACmDD;;EAEE,WAAA;CDjDD;AC2DD;EACE,0BAAA;CDzDD;ACgED;;EAEE,kBAAA;CD9DD;ACqED;EACE,mBAAA;CDnED;AC2ED;EACE,eAAA;EACA,iBAAA;CDzED;ACgFD;EACE,iBAAA;EACA,YAAA;CD9ED;ACqFD;EACE,eAAA;CDnFD;AC0FD;;EAEE,eAAA;EACA,eAAA;EACA,mBAAA;EACA,yBAAA;CDxFD;AC2FD;EACE,YAAA;CDzFD;AC4FD;EACE,gBAAA;CD1FD;ACoGD;EACE,UAAA;CDlGD;ACyGD;EACE,iBAAA;CDvGD;ACiHD;EACE,iBAAA;CD/GD;ACsHD;EACE,gCAAA;KAAA,6BAAA;UAAA,wBAAA;EACA,UAAA;CDpHD;AC2HD;EACE,eAAA;CDzHD;ACgID;;;;EAIE,kCAAA;EACA,eAAA;CD9HD;ACgJD;;;;;EAKE,eAAA;EACA,cAAA;EACA,UAAA;CD9ID;ACqJD;EACE,kBAAA;CDnJD;AC6JD;;EAEE,qBAAA;CD3JD;ACsKD;;;;EAIE,2BAAA;EACA,gBAAA;CDpKD;AC2KD;;EAEE,gBAAA;CDzKD;ACgLD;;EAEE,UAAA;EACA,WAAA;CD9KD;ACsLD;EACE,oBAAA;CDpLD;AC+LD;;EAEE,+BAAA;KAAA,4BAAA;UAAA,uBAAA;EACA,WAAA;CD7LD;ACsMD;;EAEE,aAAA;CDpMD;AC4MD;EACE,8BAAA;EACA,gCAAA;KAAA,6BAAA;UAAA,wBAAA;CD1MD;ACmND;;EAEE,yBAAA;CDjND;ACwND;EACE,0BAAA;EACA,cAAA;EACA,+BAAA;CDtND;AC8ND;EACE,UAAA;EACA,WAAA;CD5ND;ACmOD;EACE,eAAA;CDjOD;ACyOD;EACE,kBAAA;CDvOD;ACiPD;EACE,0BAAA;EACA,kBAAA;CD/OD;ACkPD;;EAEE,WAAA;CDhPD;AACD,qFAAqF;AElFrF;EA7FI;;;IAGI,mCAAA;IACA,uBAAA;IACA,oCAAA;YAAA,4BAAA;IACA,6BAAA;GFkLL;EE/KC;;IAEI,2BAAA;GFiLL;EE9KC;IACI,6BAAA;GFgLL;EE7KC;IACI,8BAAA;GF+KL;EE1KC;;IAEI,YAAA;GF4KL;EEzKC;;IAEI,uBAAA;IACA,yBAAA;GF2KL;EExKC;IACI,4BAAA;GF0KL;EEvKC;;IAEI,yBAAA;GFyKL;EEtKC;IACI,2BAAA;GFwKL;EErKC;;;IAGI,WAAA;IACA,UAAA;GFuKL;EEpKC;;IAEI,wBAAA;GFsKL;EEhKC;IACI,cAAA;GFkKL;EEhKC;;IAGQ,kCAAA;GFiKT;EE9JC;IACI,uBAAA;GFgKL;EE7JC;IACI,qCAAA;GF+JL;EEhKC;;IAKQ,kCAAA;GF+JT;EE5JC;;IAGQ,kCAAA;GF6JT;CACF;AGnPD;EACE,oCAAA;EACA,sDAAA;EACA,gYAAA;CHqPD;AG7OD;EACE,mBAAA;EACA,SAAA;EACA,sBAAA;EACA,oCAAA;EACA,mBAAA;EACA,oBAAA;EACA,eAAA;EACA,oCAAA;EACA,mCAAA;CH+OD;AG3OmC;EAAW,eAAA;CH8O9C;AG7OmC;EAAW,eAAA;CHgP9C;AG9OmC;;EAAW,iBAAA;CHkP9C;AGjPmC;EAAW,iBAAA;CHoP9C;AGnPmC;EAAW,iBAAA;CHsP9C;AGrPmC;EAAW,iBAAA;CHwP9C;AGvPmC;EAAW,iBAAA;CH0P9C;AGzPmC;EAAW,iBAAA;CH4P9C;AG3PmC;EAAW,iBAAA;CH8P9C;AG7PmC;EAAW,iBAAA;CHgQ9C;AG/PmC;EAAW,iBAAA;CHkQ9C;AGjQmC;EAAW,iBAAA;CHoQ9C;AGnQmC;EAAW,iBAAA;CHsQ9C;AGrQmC;EAAW,iBAAA;CHwQ9C;AGvQmC;EAAW,iBAAA;CH0Q9C;AGzQmC;EAAW,iBAAA;CH4Q9C;AG3QmC;EAAW,iBAAA;CH8Q9C;AG7QmC;EAAW,iBAAA;CHgR9C;AG/QmC;EAAW,iBAAA;CHkR9C;AGjRmC;EAAW,iBAAA;CHoR9C;AGnRmC;EAAW,iBAAA;CHsR9C;AGrRmC;EAAW,iBAAA;CHwR9C;AGvRmC;EAAW,iBAAA;CH0R9C;AGzRmC;EAAW,iBAAA;CH4R9C;AG3RmC;EAAW,iBAAA;CH8R9C;AG7RmC;EAAW,iBAAA;CHgS9C;AG/RmC;EAAW,iBAAA;CHkS9C;AGjSmC;EAAW,iBAAA;CHoS9C;AGnSmC;EAAW,iBAAA;CHsS9C;AGrSmC;EAAW,iBAAA;CHwS9C;AGvSmC;EAAW,iBAAA;CH0S9C;AGzSmC;EAAW,iBAAA;CH4S9C;AG3SmC;EAAW,iBAAA;CH8S9C;AG7SmC;EAAW,iBAAA;CHgT9C;AG/SmC;EAAW,iBAAA;CHkT9C;AGjTmC;EAAW,iBAAA;CHoT9C;AGnTmC;EAAW,iBAAA;CHsT9C;AGrTmC;EAAW,iBAAA;CHwT9C;AGvTmC;EAAW,iBAAA;CH0T9C;AGzTmC;EAAW,iBAAA;CH4T9C;AG3TmC;EAAW,iBAAA;CH8T9C;AG7TmC;EAAW,iBAAA;CHgU9C;AG/TmC;EAAW,iBAAA;CHkU9C;AGjUmC;EAAW,iBAAA;CHoU9C;AGnUmC;EAAW,iBAAA;CHsU9C;AGrUmC;EAAW,iBAAA;CHwU9C;AGvUmC;EAAW,iBAAA;CH0U9C;AGzUmC;EAAW,iBAAA;CH4U9C;AG3UmC;EAAW,iBAAA;CH8U9C;AG7UmC;EAAW,iBAAA;CHgV9C;AG/UmC;EAAW,iBAAA;CHkV9C;AGjVmC;EAAW,iBAAA;CHoV9C;AGnVmC;EAAW,iBAAA;CHsV9C;AGrVmC;EAAW,iBAAA;CHwV9C;AGvVmC;EAAW,iBAAA;CH0V9C;AGzVmC;EAAW,iBAAA;CH4V9C;AG3VmC;EAAW,iBAAA;CH8V9C;AG7VmC;EAAW,iBAAA;CHgW9C;AG/VmC;EAAW,iBAAA;CHkW9C;AGjWmC;EAAW,iBAAA;CHoW9C;AGnWmC;EAAW,iBAAA;CHsW9C;AGrWmC;EAAW,iBAAA;CHwW9C;AGvWmC;EAAW,iBAAA;CH0W9C;AGzWmC;EAAW,iBAAA;CH4W9C;AG3WmC;EAAW,iBAAA;CH8W9C;AG7WmC;EAAW,iBAAA;CHgX9C;AG/WmC;EAAW,iBAAA;CHkX9C;AGjXmC;EAAW,iBAAA;CHoX9C;AGnXmC;EAAW,iBAAA;CHsX9C;AGrXmC;EAAW,iBAAA;CHwX9C;AGvXmC;EAAW,iBAAA;CH0X9C;AGzXmC;EAAW,iBAAA;CH4X9C;AG3XmC;EAAW,iBAAA;CH8X9C;AG7XmC;EAAW,iBAAA;CHgY9C;AG/XmC;EAAW,iBAAA;CHkY9C;AGjYmC;EAAW,iBAAA;CHoY9C;AGnYmC;EAAW,iBAAA;CHsY9C;AGrYmC;EAAW,iBAAA;CHwY9C;AGvYmC;EAAW,iBAAA;CH0Y9C;AGzYmC;EAAW,iBAAA;CH4Y9C;AG3YmC;EAAW,iBAAA;CH8Y9C;AG7YmC;EAAW,iBAAA;CHgZ9C;AG/YmC;EAAW,iBAAA;CHkZ9C;AGjZmC;EAAW,iBAAA;CHoZ9C;AGnZmC;EAAW,iBAAA;CHsZ9C;AGrZmC;EAAW,iBAAA;CHwZ9C;AGvZmC;EAAW,iBAAA;CH0Z9C;AGzZmC;EAAW,iBAAA;CH4Z9C;AG3ZmC;EAAW,iBAAA;CH8Z9C;AG7ZmC;EAAW,iBAAA;CHga9C;AG/ZmC;EAAW,iBAAA;CHka9C;AGjamC;EAAW,iBAAA;CHoa9C;AGnamC;EAAW,iBAAA;CHsa9C;AGramC;EAAW,iBAAA;CHwa9C;AGvamC;EAAW,iBAAA;CH0a9C;AGzamC;EAAW,iBAAA;CH4a9C;AG3amC;EAAW,iBAAA;CH8a9C;AG7amC;EAAW,iBAAA;CHgb9C;AG/amC;EAAW,iBAAA;CHkb9C;AGjbmC;EAAW,iBAAA;CHob9C;AGnbmC;EAAW,iBAAA;CHsb9C;AGrbmC;EAAW,iBAAA;CHwb9C;AGvbmC;EAAW,iBAAA;CH0b9C;AGzbmC;EAAW,iBAAA;CH4b9C;AG3bmC;EAAW,iBAAA;CH8b9C;AG7bmC;EAAW,iBAAA;CHgc9C;AG/bmC;EAAW,iBAAA;CHkc9C;AGjcmC;EAAW,iBAAA;CHoc9C;AGncmC;EAAW,iBAAA;CHsc9C;AGrcmC;EAAW,iBAAA;CHwc9C;AGvcmC;EAAW,iBAAA;CH0c9C;AGzcmC;EAAW,iBAAA;CH4c9C;AG3cmC;EAAW,iBAAA;CH8c9C;AG7cmC;EAAW,iBAAA;CHgd9C;AG/cmC;EAAW,iBAAA;CHkd9C;AGjdmC;EAAW,iBAAA;CHod9C;AGndmC;EAAW,iBAAA;CHsd9C;AGrdmC;EAAW,iBAAA;CHwd9C;AGvdmC;EAAW,iBAAA;CH0d9C;AGzdmC;EAAW,iBAAA;CH4d9C;AG3dmC;EAAW,iBAAA;CH8d9C;AG7dmC;EAAW,iBAAA;CHge9C;AG/dmC;EAAW,iBAAA;CHke9C;AGjemC;EAAW,iBAAA;CHoe9C;AGnemC;EAAW,iBAAA;CHse9C;AGremC;EAAW,iBAAA;CHwe9C;AGvemC;EAAW,iBAAA;CH0e9C;AGzemC;EAAW,iBAAA;CH4e9C;AG3emC;EAAW,iBAAA;CH8e9C;AG7emC;EAAW,iBAAA;CHgf9C;AG/emC;EAAW,iBAAA;CHkf9C;AGjfmC;EAAW,iBAAA;CHof9C;AGnfmC;EAAW,iBAAA;CHsf9C;AGrfmC;EAAW,iBAAA;CHwf9C;AGvfmC;EAAW,iBAAA;CH0f9C;AGzfmC;EAAW,iBAAA;CH4f9C;AG3fmC;EAAW,iBAAA;CH8f9C;AG7fmC;EAAW,iBAAA;CHggB9C;AG/fmC;EAAW,iBAAA;CHkgB9C;AGjgBmC;EAAW,iBAAA;CHogB9C;AGngBmC;EAAW,iBAAA;CHsgB9C;AGrgBmC;EAAW,iBAAA;CHwgB9C;AGvgBmC;EAAW,iBAAA;CH0gB9C;AGzgBmC;EAAW,iBAAA;CH4gB9C;AG3gBmC;EAAW,iBAAA;CH8gB9C;AG7gBmC;EAAW,iBAAA;CHghB9C;AG/gBmC;EAAW,iBAAA;CHkhB9C;AGjhBmC;EAAW,iBAAA;CHohB9C;AGnhBmC;EAAW,iBAAA;CHshB9C;AGrhBmC;EAAW,iBAAA;CHwhB9C;AGvhBmC;EAAW,iBAAA;CH0hB9C;AGzhBmC;EAAW,iBAAA;CH4hB9C;AG3hBmC;EAAW,iBAAA;CH8hB9C;AG7hBmC;EAAW,iBAAA;CHgiB9C;AG/hBmC;EAAW,iBAAA;CHkiB9C;AGjiBmC;EAAW,iBAAA;CHoiB9C;AGniBmC;EAAW,iBAAA;CHsiB9C;AGriBmC;EAAW,iBAAA;CHwiB9C;AGviBmC;EAAW,iBAAA;CH0iB9C;AGziBmC;EAAW,iBAAA;CH4iB9C;AG3iBmC;EAAW,iBAAA;CH8iB9C;AG7iBmC;EAAW,iBAAA;CHgjB9C;AG/iBmC;EAAW,iBAAA;CHkjB9C;AGjjBmC;EAAW,iBAAA;CHojB9C;AGnjBmC;EAAW,iBAAA;CHsjB9C;AGrjBmC;EAAW,iBAAA;CHwjB9C;AGvjBmC;EAAW,iBAAA;CH0jB9C;AGzjBmC;EAAW,iBAAA;CH4jB9C;AG3jBmC;EAAW,iBAAA;CH8jB9C;AG7jBmC;EAAW,iBAAA;CHgkB9C;AG/jBmC;EAAW,iBAAA;CHkkB9C;AGjkBmC;EAAW,iBAAA;CHokB9C;AGnkBmC;EAAW,iBAAA;CHskB9C;AGrkBmC;EAAW,iBAAA;CHwkB9C;AGvkBmC;EAAW,iBAAA;CH0kB9C;AGzkBmC;EAAW,iBAAA;CH4kB9C;AG3kBmC;EAAW,iBAAA;CH8kB9C;AG7kBmC;EAAW,iBAAA;CHglB9C;AG/kBmC;EAAW,iBAAA;CHklB9C;AGjlBmC;EAAW,iBAAA;CHolB9C;AGnlBmC;EAAW,iBAAA;CHslB9C;AGrlBmC;EAAW,iBAAA;CHwlB9C;AGvlBmC;EAAW,iBAAA;CH0lB9C;AGzlBmC;EAAW,iBAAA;CH4lB9C;AG3lBmC;EAAW,iBAAA;CH8lB9C;AG7lBmC;EAAW,iBAAA;CHgmB9C;AG/lBmC;EAAW,iBAAA;CHkmB9C;AGjmBmC;EAAW,iBAAA;CHomB9C;AGnmBmC;EAAW,iBAAA;CHsmB9C;AGrmBmC;EAAW,iBAAA;CHwmB9C;AGvmBmC;EAAW,iBAAA;CH0mB9C;AGzmBmC;EAAW,iBAAA;CH4mB9C;AG3mBmC;EAAW,iBAAA;CH8mB9C;AG7mBmC;EAAW,iBAAA;CHgnB9C;AG/mBmC;EAAW,iBAAA;CHknB9C;AGjnBmC;EAAW,iBAAA;CHonB9C;AGnnBmC;EAAW,iBAAA;CHsnB9C;AGrnBmC;EAAW,iBAAA;CHwnB9C;AGvnBmC;EAAW,iBAAA;CH0nB9C;AGznBmC;EAAW,iBAAA;CH4nB9C;AG3nBmC;EAAW,iBAAA;CH8nB9C;AG7nBmC;EAAW,iBAAA;CHgoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AG/nBmC;EAAW,iBAAA;CHkoB9C;AGjoBmC;EAAW,iBAAA;CHooB9C;AGnoBmC;EAAW,iBAAA;CHsoB9C;AGroBmC;EAAW,iBAAA;CHwoB9C;AGvoBmC;EAAW,iBAAA;CH0oB9C;AGzoBmC;EAAW,iBAAA;CH4oB9C;AG3oBmC;EAAW,iBAAA;CH8oB9C;AG7oBmC;EAAW,iBAAA;CHgpB9C;AG/oBmC;EAAW,iBAAA;CHkpB9C;AGjpBmC;EAAW,iBAAA;CHopB9C;AGnpBmC;EAAW,iBAAA;CHspB9C;AGrpBmC;EAAW,iBAAA;CHwpB9C;AGvpBmC;EAAW,iBAAA;CH0pB9C;AGzpBmC;EAAW,iBAAA;CH4pB9C;AG3pBmC;EAAW,iBAAA;CH8pB9C;AG7pBmC;EAAW,iBAAA;CHgqB9C;AG/pBmC;EAAW,iBAAA;CHkqB9C;AGjqBmC;EAAW,iBAAA;CHoqB9C;AGnqBmC;EAAW,iBAAA;CHsqB9C;AGrqBmC;EAAW,iBAAA;CHwqB9C;AGvqBmC;EAAW,iBAAA;CH0qB9C;AGzqBmC;EAAW,iBAAA;CH4qB9C;AG3qBmC;EAAW,iBAAA;CH8qB9C;AG7qBmC;EAAW,iBAAA;CHgrB9C;AG/qBmC;EAAW,iBAAA;CHkrB9C;AGjrBmC;EAAW,iBAAA;CHorB9C;AGnrBmC;EAAW,iBAAA;CHsrB9C;AGrrBmC;EAAW,iBAAA;CHwrB9C;AGvrBmC;EAAW,iBAAA;CH0rB9C;AGzrBmC;EAAW,iBAAA;CH4rB9C;AG3rBmC;EAAW,iBAAA;CH8rB9C;AG7rBmC;EAAW,iBAAA;CHgsB9C;AG/rBmC;EAAW,iBAAA;CHksB9C;AGjsBmC;EAAW,iBAAA;CHosB9C;AGnsBmC;EAAW,iBAAA;CHssB9C;AGrsBmC;EAAW,iBAAA;CHwsB9C;AGvsBmC;EAAW,iBAAA;CH0sB9C;AGzsBmC;EAAW,iBAAA;CH4sB9C;AG3sBmC;EAAW,iBAAA;CH8sB9C;AG7sBmC;EAAW,iBAAA;CHgtB9C;AG/sBmC;EAAW,iBAAA;CHktB9C;AGjtBmC;EAAW,iBAAA;CHotB9C;AGntBmC;EAAW,iBAAA;CHstB9C;AGrtBmC;EAAW,iBAAA;CHwtB9C;AGvtBmC;EAAW,iBAAA;CH0tB9C;AGztBmC;EAAW,iBAAA;CH4tB9C;AG3tBmC;EAAW,iBAAA;CH8tB9C;AG7tBmC;EAAW,iBAAA;CHguB9C;AG/tBmC;EAAW,iBAAA;CHkuB9C;AGjuBmC;EAAW,iBAAA;CHouB9C;AGnuBmC;EAAW,iBAAA;CHsuB9C;AGruBmC;EAAW,iBAAA;CHwuB9C;AGvuBmC;EAAW,iBAAA;CH0uB9C;AGzuBmC;EAAW,iBAAA;CH4uB9C;AG3uBmC;EAAW,iBAAA;CH8uB9C;AG7uBmC;EAAW,iBAAA;CHgvB9C;AIthCD;ECgEE,+BAAA;EACG,4BAAA;EACK,uBAAA;CLy9BT;AIxhCD;;EC6DE,+BAAA;EACG,4BAAA;EACK,uBAAA;CL+9BT;AIthCD;EACE,gBAAA;EACA,8CAAA;CJwhCD;AIrhCD;EACE,4DAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,0BAAA;CJuhCD;AInhCD;;;;EAIE,qBAAA;EACA,mBAAA;EACA,qBAAA;CJqhCD;AI/gCD;EACE,eAAA;EACA,sBAAA;CJihCD;AI/gCC;;EAEE,eAAA;EACA,2BAAA;CJihCH;AI9gCC;EErDA,qBAAA;EAEA,2CAAA;EACA,qBAAA;CNqkCD;AIxgCD;EACE,UAAA;CJ0gCD;AIpgCD;EACE,uBAAA;CJsgCD;AIlgCD;;;;;EGvEE,eAAA;EACA,gBAAA;EACA,aAAA;CPglCD;AItgCD;EACE,mBAAA;CJwgCD;AIlgCD;EACE,aAAA;EACA,wBAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;EC6FA,yCAAA;EACK,oCAAA;EACG,iCAAA;EEvLR,sBAAA;EACA,gBAAA;EACA,aAAA;CPgmCD;AIlgCD;EACE,mBAAA;CJogCD;AI9/BD;EACE,iBAAA;EACA,oBAAA;EACA,UAAA;EACA,8BAAA;CJggCD;AIx/BD;EACE,mBAAA;EACA,WAAA;EACA,YAAA;EACA,aAAA;EACA,WAAA;EACA,iBAAA;EACA,uBAAA;EACA,UAAA;CJ0/BD;AIl/BC;;EAEE,iBAAA;EACA,YAAA;EACA,aAAA;EACA,UAAA;EACA,kBAAA;EACA,WAAA;CJo/BH;AIz+BD;EACE,gBAAA;CJ2+BD;AQloCD;;;;;;;;;;;;EAEE,qBAAA;EACA,iBAAA;EACA,iBAAA;EACA,eAAA;CR8oCD;AQnpCD;;;;;;;;;;;;;;;;;;;;;;;;EASI,oBAAA;EACA,eAAA;EACA,eAAA;CRoqCH;AQhqCD;;;;;;EAGE,iBAAA;EACA,oBAAA;CRqqCD;AQzqCD;;;;;;;;;;;;EAQI,eAAA;CR+qCH;AQ5qCD;;;;;;EAGE,iBAAA;EACA,oBAAA;CRirCD;AQrrCD;;;;;;;;;;;;EAQI,eAAA;CR2rCH;AQvrCD;;EAAU,gBAAA;CR2rCT;AQ1rCD;;EAAU,gBAAA;CR8rCT;AQ7rCD;;EAAU,gBAAA;CRisCT;AQhsCD;;EAAU,gBAAA;CRosCT;AQnsCD;;EAAU,gBAAA;CRusCT;AQtsCD;;EAAU,gBAAA;CR0sCT;AQpsCD;EACE,iBAAA;CRssCD;AQnsCD;EACE,oBAAA;EACA,gBAAA;EACA,iBAAA;EACA,iBAAA;CRqsCD;AQhsCD;EAAA;IAFI,gBAAA;GRssCD;CACF;AQ9rCD;;EAEE,eAAA;CRgsCD;AQ7rCD;;EAEE,0BAAA;EACA,cAAA;CR+rCD;AQ3rCD;EAAuB,iBAAA;CR8rCtB;AQ7rCD;EAAuB,kBAAA;CRgsCtB;AQ/rCD;EAAuB,mBAAA;CRksCtB;AQjsCD;EAAuB,oBAAA;CRosCtB;AQnsCD;EAAuB,oBAAA;CRssCtB;AQnsCD;EAAuB,0BAAA;CRssCtB;AQrsCD;EAAuB,0BAAA;CRwsCtB;AQvsCD;EAAuB,2BAAA;CR0sCtB;AQvsCD;EACE,eAAA;CRysCD;AQvsCD;ECrGE,eAAA;CT+yCD;AS9yCC;;EAEE,eAAA;CTgzCH;AQ3sCD;ECxGE,eAAA;CTszCD;ASrzCC;;EAEE,eAAA;CTuzCH;AQ/sCD;EC3GE,eAAA;CT6zCD;AS5zCC;;EAEE,eAAA;CT8zCH;AQntCD;EC9GE,eAAA;CTo0CD;ASn0CC;;EAEE,eAAA;CTq0CH;AQvtCD;ECjHE,eAAA;CT20CD;AS10CC;;EAEE,eAAA;CT40CH;AQvtCD;EAGE,YAAA;EE3HA,0BAAA;CVm1CD;AUl1CC;;EAEE,0BAAA;CVo1CH;AQztCD;EE9HE,0BAAA;CV01CD;AUz1CC;;EAEE,0BAAA;CV21CH;AQ7tCD;EEjIE,0BAAA;CVi2CD;AUh2CC;;EAEE,0BAAA;CVk2CH;AQjuCD;EEpIE,0BAAA;CVw2CD;AUv2CC;;EAEE,0BAAA;CVy2CH;AQruCD;EEvIE,0BAAA;CV+2CD;AU92CC;;EAEE,0BAAA;CVg3CH;AQpuCD;EACE,oBAAA;EACA,oBAAA;EACA,iCAAA;CRsuCD;AQ9tCD;;EAEE,cAAA;EACA,oBAAA;CRguCD;AQnuCD;;;;EAMI,iBAAA;CRmuCH;AQ5tCD;EACE,gBAAA;EACA,iBAAA;CR8tCD;AQ1tCD;EALE,gBAAA;EACA,iBAAA;EAMA,kBAAA;CR6tCD;AQ/tCD;EAKI,sBAAA;EACA,kBAAA;EACA,mBAAA;CR6tCH;AQxtCD;EACE,cAAA;EACA,oBAAA;CR0tCD;AQxtCD;;EAEE,wBAAA;CR0tCD;AQxtCD;EACE,kBAAA;CR0tCD;AQxtCD;EACE,eAAA;CR0tCD;AQjsCD;EAAA;IAVM,YAAA;IACA,aAAA;IACA,YAAA;IACA,kBAAA;IGtNJ,iBAAA;IACA,wBAAA;IACA,oBAAA;GXs6CC;EQ3sCH;IAHM,mBAAA;GRitCH;CACF;AQxsCD;;EAGE,aAAA;EACA,kCAAA;CRysCD;AQvsCD;EACE,eAAA;EA9IqB,0BAAA;CRw1CtB;AQrsCD;EACE,mBAAA;EACA,iBAAA;EACA,kBAAA;EACA,+BAAA;CRusCD;AQlsCG;;;EACE,iBAAA;CRssCL;AQhtCD;;;EAmBI,eAAA;EACA,eAAA;EACA,wBAAA;EACA,eAAA;CRksCH;AQhsCG;;;EACE,uBAAA;CRosCL;AQ5rCD;;EAEE,oBAAA;EACA,gBAAA;EACA,gCAAA;EACA,eAAA;EACA,kBAAA;CR8rCD;AQxrCG;;;;;;EAAW,YAAA;CRgsCd;AQ/rCG;;;;;;EACE,uBAAA;CRssCL;AQhsCD;EACE,oBAAA;EACA,mBAAA;EACA,wBAAA;CRksCD;AYx+CD;;;;EAIE,+DAAA;CZ0+CD;AYt+CD;EACE,iBAAA;EACA,eAAA;EACA,eAAA;EACA,0BAAA;EACA,mBAAA;CZw+CD;AYp+CD;EACE,iBAAA;EACA,eAAA;EACA,eAAA;EACA,0BAAA;EACA,mBAAA;EACA,uDAAA;UAAA,+CAAA;CZs+CD;AY5+CD;EASI,WAAA;EACA,gBAAA;EACA,kBAAA;EACA,yBAAA;UAAA,iBAAA;CZs+CH;AYj+CD;EACE,eAAA;EACA,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,wBAAA;EACA,sBAAA;EACA,sBAAA;EACA,eAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;CZm+CD;AY9+CD;EAeI,WAAA;EACA,mBAAA;EACA,eAAA;EACA,sBAAA;EACA,8BAAA;EACA,iBAAA;CZk+CH;AY79CD;EACE,kBAAA;EACA,mBAAA;CZ+9CD;AazhDD;ECHE,mBAAA;EACA,kBAAA;EACA,mBAAA;EACA,oBAAA;Cd+hDD;AazhDC;EAAA;IAFE,aAAA;Gb+hDD;CACF;Aa3hDC;EAAA;IAFE,aAAA;GbiiDD;CACF;Aa7hDD;EAAA;IAFI,cAAA;GbmiDD;CACF;Aa1hDD;ECvBE,mBAAA;EACA,kBAAA;EACA,mBAAA;EACA,oBAAA;CdojDD;AavhDD;ECvBE,mBAAA;EACA,oBAAA;CdijDD;AejjDG;EACE,mBAAA;EAEA,gBAAA;EAEA,mBAAA;EACA,oBAAA;CfijDL;AejiDG;EACE,YAAA;CfmiDL;Ae5hDC;EACE,YAAA;Cf8hDH;Ae/hDC;EACE,oBAAA;CfiiDH;AeliDC;EACE,oBAAA;CfoiDH;AeriDC;EACE,WAAA;CfuiDH;AexiDC;EACE,oBAAA;Cf0iDH;Ae3iDC;EACE,oBAAA;Cf6iDH;Ae9iDC;EACE,WAAA;CfgjDH;AejjDC;EACE,oBAAA;CfmjDH;AepjDC;EACE,oBAAA;CfsjDH;AevjDC;EACE,WAAA;CfyjDH;Ae1jDC;EACE,oBAAA;Cf4jDH;Ae7jDC;EACE,mBAAA;Cf+jDH;AejjDC;EACE,YAAA;CfmjDH;AepjDC;EACE,oBAAA;CfsjDH;AevjDC;EACE,oBAAA;CfyjDH;Ae1jDC;EACE,WAAA;Cf4jDH;Ae7jDC;EACE,oBAAA;Cf+jDH;AehkDC;EACE,oBAAA;CfkkDH;AenkDC;EACE,WAAA;CfqkDH;AetkDC;EACE,oBAAA;CfwkDH;AezkDC;EACE,oBAAA;Cf2kDH;Ae5kDC;EACE,WAAA;Cf8kDH;Ae/kDC;EACE,oBAAA;CfilDH;AellDC;EACE,mBAAA;CfolDH;AehlDC;EACE,YAAA;CfklDH;AelmDC;EACE,WAAA;CfomDH;AermDC;EACE,mBAAA;CfumDH;AexmDC;EACE,mBAAA;Cf0mDH;Ae3mDC;EACE,UAAA;Cf6mDH;Ae9mDC;EACE,mBAAA;CfgnDH;AejnDC;EACE,mBAAA;CfmnDH;AepnDC;EACE,UAAA;CfsnDH;AevnDC;EACE,mBAAA;CfynDH;Ae1nDC;EACE,mBAAA;Cf4nDH;Ae7nDC;EACE,UAAA;Cf+nDH;AehoDC;EACE,mBAAA;CfkoDH;AenoDC;EACE,kBAAA;CfqoDH;AejoDC;EACE,WAAA;CfmoDH;AernDC;EACE,kBAAA;CfunDH;AexnDC;EACE,0BAAA;Cf0nDH;Ae3nDC;EACE,0BAAA;Cf6nDH;Ae9nDC;EACE,iBAAA;CfgoDH;AejoDC;EACE,0BAAA;CfmoDH;AepoDC;EACE,0BAAA;CfsoDH;AevoDC;EACE,iBAAA;CfyoDH;Ae1oDC;EACE,0BAAA;Cf4oDH;Ae7oDC;EACE,0BAAA;Cf+oDH;AehpDC;EACE,iBAAA;CfkpDH;AenpDC;EACE,0BAAA;CfqpDH;AetpDC;EACE,yBAAA;CfwpDH;AezpDC;EACE,gBAAA;Cf2pDH;Aa3pDD;EElCI;IACE,YAAA;GfgsDH;EezrDD;IACE,YAAA;Gf2rDD;Ee5rDD;IACE,oBAAA;Gf8rDD;Ee/rDD;IACE,oBAAA;GfisDD;EelsDD;IACE,WAAA;GfosDD;EersDD;IACE,oBAAA;GfusDD;EexsDD;IACE,oBAAA;Gf0sDD;Ee3sDD;IACE,WAAA;Gf6sDD;Ee9sDD;IACE,oBAAA;GfgtDD;EejtDD;IACE,oBAAA;GfmtDD;EeptDD;IACE,WAAA;GfstDD;EevtDD;IACE,oBAAA;GfytDD;Ee1tDD;IACE,mBAAA;Gf4tDD;Ee9sDD;IACE,YAAA;GfgtDD;EejtDD;IACE,oBAAA;GfmtDD;EeptDD;IACE,oBAAA;GfstDD;EevtDD;IACE,WAAA;GfytDD;Ee1tDD;IACE,oBAAA;Gf4tDD;Ee7tDD;IACE,oBAAA;Gf+tDD;EehuDD;IACE,WAAA;GfkuDD;EenuDD;IACE,oBAAA;GfquDD;EetuDD;IACE,oBAAA;GfwuDD;EezuDD;IACE,WAAA;Gf2uDD;Ee5uDD;IACE,oBAAA;Gf8uDD;Ee/uDD;IACE,mBAAA;GfivDD;Ee7uDD;IACE,YAAA;Gf+uDD;Ee/vDD;IACE,WAAA;GfiwDD;EelwDD;IACE,mBAAA;GfowDD;EerwDD;IACE,mBAAA;GfuwDD;EexwDD;IACE,UAAA;Gf0wDD;Ee3wDD;IACE,mBAAA;Gf6wDD;Ee9wDD;IACE,mBAAA;GfgxDD;EejxDD;IACE,UAAA;GfmxDD;EepxDD;IACE,mBAAA;GfsxDD;EevxDD;IACE,mBAAA;GfyxDD;Ee1xDD;IACE,UAAA;Gf4xDD;Ee7xDD;IACE,mBAAA;Gf+xDD;EehyDD;IACE,kBAAA;GfkyDD;Ee9xDD;IACE,WAAA;GfgyDD;EelxDD;IACE,kBAAA;GfoxDD;EerxDD;IACE,0BAAA;GfuxDD;EexxDD;IACE,0BAAA;Gf0xDD;Ee3xDD;IACE,iBAAA;Gf6xDD;Ee9xDD;IACE,0BAAA;GfgyDD;EejyDD;IACE,0BAAA;GfmyDD;EepyDD;IACE,iBAAA;GfsyDD;EevyDD;IACE,0BAAA;GfyyDD;Ee1yDD;IACE,0BAAA;Gf4yDD;Ee7yDD;IACE,iBAAA;Gf+yDD;EehzDD;IACE,0BAAA;GfkzDD;EenzDD;IACE,yBAAA;GfqzDD;EetzDD;IACE,gBAAA;GfwzDD;CACF;AahzDD;EE3CI;IACE,YAAA;Gf81DH;Eev1DD;IACE,YAAA;Gfy1DD;Ee11DD;IACE,oBAAA;Gf41DD;Ee71DD;IACE,oBAAA;Gf+1DD;Eeh2DD;IACE,WAAA;Gfk2DD;Een2DD;IACE,oBAAA;Gfq2DD;Eet2DD;IACE,oBAAA;Gfw2DD;Eez2DD;IACE,WAAA;Gf22DD;Ee52DD;IACE,oBAAA;Gf82DD;Ee/2DD;IACE,oBAAA;Gfi3DD;Eel3DD;IACE,WAAA;Gfo3DD;Eer3DD;IACE,oBAAA;Gfu3DD;Eex3DD;IACE,mBAAA;Gf03DD;Ee52DD;IACE,YAAA;Gf82DD;Ee/2DD;IACE,oBAAA;Gfi3DD;Eel3DD;IACE,oBAAA;Gfo3DD;Eer3DD;IACE,WAAA;Gfu3DD;Eex3DD;IACE,oBAAA;Gf03DD;Ee33DD;IACE,oBAAA;Gf63DD;Ee93DD;IACE,WAAA;Gfg4DD;Eej4DD;IACE,oBAAA;Gfm4DD;Eep4DD;IACE,oBAAA;Gfs4DD;Eev4DD;IACE,WAAA;Gfy4DD;Ee14DD;IACE,oBAAA;Gf44DD;Ee74DD;IACE,mBAAA;Gf+4DD;Ee34DD;IACE,YAAA;Gf64DD;Ee75DD;IACE,WAAA;Gf+5DD;Eeh6DD;IACE,mBAAA;Gfk6DD;Een6DD;IACE,mBAAA;Gfq6DD;Eet6DD;IACE,UAAA;Gfw6DD;Eez6DD;IACE,mBAAA;Gf26DD;Ee56DD;IACE,mBAAA;Gf86DD;Ee/6DD;IACE,UAAA;Gfi7DD;Eel7DD;IACE,mBAAA;Gfo7DD;Eer7DD;IACE,mBAAA;Gfu7DD;Eex7DD;IACE,UAAA;Gf07DD;Ee37DD;IACE,mBAAA;Gf67DD;Ee97DD;IACE,kBAAA;Gfg8DD;Ee57DD;IACE,WAAA;Gf87DD;Eeh7DD;IACE,kBAAA;Gfk7DD;Een7DD;IACE,0BAAA;Gfq7DD;Eet7DD;IACE,0BAAA;Gfw7DD;Eez7DD;IACE,iBAAA;Gf27DD;Ee57DD;IACE,0BAAA;Gf87DD;Ee/7DD;IACE,0BAAA;Gfi8DD;Eel8DD;IACE,iBAAA;Gfo8DD;Eer8DD;IACE,0BAAA;Gfu8DD;Eex8DD;IACE,0BAAA;Gf08DD;Ee38DD;IACE,iBAAA;Gf68DD;Ee98DD;IACE,0BAAA;Gfg9DD;Eej9DD;IACE,yBAAA;Gfm9DD;Eep9DD;IACE,gBAAA;Gfs9DD;CACF;Aa38DD;EE9CI;IACE,YAAA;Gf4/DH;Eer/DD;IACE,YAAA;Gfu/DD;Eex/DD;IACE,oBAAA;Gf0/DD;Ee3/DD;IACE,oBAAA;Gf6/DD;Ee9/DD;IACE,WAAA;GfggED;EejgED;IACE,oBAAA;GfmgED;EepgED;IACE,oBAAA;GfsgED;EevgED;IACE,WAAA;GfygED;Ee1gED;IACE,oBAAA;Gf4gED;Ee7gED;IACE,oBAAA;Gf+gED;EehhED;IACE,WAAA;GfkhED;EenhED;IACE,oBAAA;GfqhED;EethED;IACE,mBAAA;GfwhED;Ee1gED;IACE,YAAA;Gf4gED;Ee7gED;IACE,oBAAA;Gf+gED;EehhED;IACE,oBAAA;GfkhED;EenhED;IACE,WAAA;GfqhED;EethED;IACE,oBAAA;GfwhED;EezhED;IACE,oBAAA;Gf2hED;Ee5hED;IACE,WAAA;Gf8hED;Ee/hED;IACE,oBAAA;GfiiED;EeliED;IACE,oBAAA;GfoiED;EeriED;IACE,WAAA;GfuiED;EexiED;IACE,oBAAA;Gf0iED;Ee3iED;IACE,mBAAA;Gf6iED;EeziED;IACE,YAAA;Gf2iED;Ee3jED;IACE,WAAA;Gf6jED;Ee9jED;IACE,mBAAA;GfgkED;EejkED;IACE,mBAAA;GfmkED;EepkED;IACE,UAAA;GfskED;EevkED;IACE,mBAAA;GfykED;Ee1kED;IACE,mBAAA;Gf4kED;Ee7kED;IACE,UAAA;Gf+kED;EehlED;IACE,mBAAA;GfklED;EenlED;IACE,mBAAA;GfqlED;EetlED;IACE,UAAA;GfwlED;EezlED;IACE,mBAAA;Gf2lED;Ee5lED;IACE,kBAAA;Gf8lED;Ee1lED;IACE,WAAA;Gf4lED;Ee9kED;IACE,kBAAA;GfglED;EejlED;IACE,0BAAA;GfmlED;EeplED;IACE,0BAAA;GfslED;EevlED;IACE,iBAAA;GfylED;Ee1lED;IACE,0BAAA;Gf4lED;Ee7lED;IACE,0BAAA;Gf+lED;EehmED;IACE,iBAAA;GfkmED;EenmED;IACE,0BAAA;GfqmED;EetmED;IACE,0BAAA;GfwmED;EezmED;IACE,iBAAA;Gf2mED;Ee5mED;IACE,0BAAA;Gf8mED;Ee/mED;IACE,yBAAA;GfinED;EelnED;IACE,gBAAA;GfonED;CACF;AgBxrED;EACE,8BAAA;ChB0rED;AgBxrED;EACE,iBAAA;EACA,oBAAA;EACA,eAAA;EACA,iBAAA;ChB0rED;AgBxrED;EACE,iBAAA;ChB0rED;AgBprED;EACE,YAAA;EACA,gBAAA;EACA,oBAAA;ChBsrED;AgBzrED;;;;;;EAWQ,aAAA;EACA,wBAAA;EACA,oBAAA;EACA,8BAAA;ChBsrEP;AgBpsED;EAoBI,uBAAA;EACA,iCAAA;ChBmrEH;AgBxsED;;;;;;EA8BQ,cAAA;ChBkrEP;AgBhtED;EAoCI,8BAAA;ChB+qEH;AgBntED;EAyCI,0BAAA;ChB6qEH;AgBtqED;;;;;;EAOQ,aAAA;ChBuqEP;AgB5pED;EACE,0BAAA;ChB8pED;AgB/pED;;;;;;EAQQ,0BAAA;ChB+pEP;AgBvqED;;EAeM,yBAAA;ChB4pEL;AgBlpED;EAEI,0BAAA;ChBmpEH;AgB1oED;EAEI,0BAAA;ChB2oEH;AgBloED;EACE,iBAAA;EACA,YAAA;EACA,sBAAA;ChBooED;AgB/nEG;;EACE,iBAAA;EACA,YAAA;EACA,oBAAA;ChBkoEL;AiB9wEC;;;;;;;;;;;;EAOI,0BAAA;CjBqxEL;AiB/wEC;;;;;EAMI,0BAAA;CjBgxEL;AiBnyEC;;;;;;;;;;;;EAOI,0BAAA;CjB0yEL;AiBpyEC;;;;;EAMI,0BAAA;CjBqyEL;AiBxzEC;;;;;;;;;;;;EAOI,0BAAA;CjB+zEL;AiBzzEC;;;;;EAMI,0BAAA;CjB0zEL;AiB70EC;;;;;;;;;;;;EAOI,0BAAA;CjBo1EL;AiB90EC;;;;;EAMI,0BAAA;CjB+0EL;AiBl2EC;;;;;;;;;;;;EAOI,0BAAA;CjBy2EL;AiBn2EC;;;;;EAMI,0BAAA;CjBo2EL;AgBltED;EACE,iBAAA;EACA,kBAAA;ChBotED;AgBvpED;EAAA;IA1DI,YAAA;IACA,oBAAA;IACA,mBAAA;IACA,6CAAA;IACA,0BAAA;GhBqtED;EgB/pEH;IAlDM,iBAAA;GhBotEH;EgBlqEH;;;;;;IAzCY,oBAAA;GhBmtET;EgB1qEH;IAjCM,UAAA;GhB8sEH;EgB7qEH;;;;;;IAxBY,eAAA;GhB6sET;EgBrrEH;;;;;;IApBY,gBAAA;GhBitET;EgB7rEH;;;;IAPY,iBAAA;GhB0sET;CACF;AkBp6ED;EACE,WAAA;EACA,UAAA;EACA,UAAA;EAIA,aAAA;ClBm6ED;AkBh6ED;EACE,eAAA;EACA,YAAA;EACA,WAAA;EACA,oBAAA;EACA,gBAAA;EACA,qBAAA;EACA,eAAA;EACA,UAAA;EACA,iCAAA;ClBk6ED;AkB/5ED;EACE,sBAAA;EACA,gBAAA;EACA,mBAAA;EACA,kBAAA;ClBi6ED;AkBt5ED;Eb4BE,+BAAA;EACG,4BAAA;EACK,uBAAA;CL63ET;AkBt5ED;;EAEE,gBAAA;EACA,mBAAA;EACA,oBAAA;ClBw5ED;AkBr5ED;EACE,eAAA;ClBu5ED;AkBn5ED;EACE,eAAA;EACA,YAAA;ClBq5ED;AkBj5ED;;EAEE,aAAA;ClBm5ED;AkB/4ED;;;EZvEE,qBAAA;EAEA,2CAAA;EACA,qBAAA;CN09ED;AkB/4ED;EACE,eAAA;EACA,iBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;ClBi5ED;AkBv3ED;EACE,eAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,0BAAA;EACA,uBAAA;EACA,0BAAA;EACA,mBAAA;EbxDA,yDAAA;EACQ,iDAAA;EAyHR,uFAAA;EACK,0EAAA;EACG,uEAAA;CL0zET;AmBl8EC;EACE,sBAAA;EACA,WAAA;EdUF,uFAAA;EACQ,+EAAA;CL27ET;AK15EC;EACE,eAAA;EACA,WAAA;CL45EH;AK15EC;EAA0B,eAAA;CL65E3B;AK55EC;EAAgC,eAAA;CL+5EjC;AkB/3EC;;;EAGE,0BAAA;EACA,WAAA;ClBi4EH;AkB93EC;;EAEE,oBAAA;ClBg4EH;AkB53EC;EACE,aAAA;ClB83EH;AkBl3ED;EACE,yBAAA;ClBo3ED;AkB50ED;EAtBI;;;;IACE,kBAAA;GlBw2EH;EkBr2EC;;;;;;;;IAEE,kBAAA;GlB62EH;EkB12EC;;;;;;;;IAEE,kBAAA;GlBk3EH;CACF;AkBx2ED;EACE,oBAAA;ClB02ED;AkBl2ED;;EAEE,mBAAA;EACA,eAAA;EACA,iBAAA;EACA,oBAAA;ClBo2ED;AkBz2ED;;EAQI,iBAAA;EACA,mBAAA;EACA,iBAAA;EACA,oBAAA;EACA,gBAAA;ClBq2EH;AkBl2ED;;;;EAIE,mBAAA;EACA,mBAAA;EACA,mBAAA;ClBo2ED;AkBj2ED;;EAEE,iBAAA;ClBm2ED;AkB/1ED;;EAEE,mBAAA;EACA,sBAAA;EACA,mBAAA;EACA,iBAAA;EACA,uBAAA;EACA,oBAAA;EACA,gBAAA;ClBi2ED;AkB/1ED;;EAEE,cAAA;EACA,kBAAA;ClBi2ED;AkBx1EC;;;;;;EAGE,oBAAA;ClB61EH;AkBv1EC;;;;EAEE,oBAAA;ClB21EH;AkBr1EC;;;;EAGI,oBAAA;ClBw1EL;AkB70ED;EAEE,iBAAA;EACA,oBAAA;EAEA,iBAAA;EACA,iBAAA;ClB60ED;AkB30EC;;EAEE,gBAAA;EACA,iBAAA;ClB60EH;AkBh0ED;EC7PE,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CnBgkFD;AmB9jFC;EACE,aAAA;EACA,kBAAA;CnBgkFH;AmB7jFC;;EAEE,aAAA;CnB+jFH;AkB50ED;EAEI,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;ClB60EH;AkBn1ED;EASI,aAAA;EACA,kBAAA;ClB60EH;AkBv1ED;;EAcI,aAAA;ClB60EH;AkB31ED;EAiBI,aAAA;EACA,iBAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;ClB60EH;AkBz0ED;ECzRE,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CnBqmFD;AmBnmFC;EACE,aAAA;EACA,kBAAA;CnBqmFH;AmBlmFC;;EAEE,aAAA;CnBomFH;AkBr1ED;EAEI,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;ClBs1EH;AkB51ED;EASI,aAAA;EACA,kBAAA;ClBs1EH;AkBh2ED;;EAcI,aAAA;ClBs1EH;AkBp2ED;EAiBI,aAAA;EACA,iBAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;ClBs1EH;AkB70ED;EAEE,mBAAA;ClB80ED;AkBh1ED;EAMI,sBAAA;ClB60EH;AkBz0ED;EACE,mBAAA;EACA,OAAA;EACA,SAAA;EACA,WAAA;EACA,eAAA;EACA,YAAA;EACA,aAAA;EACA,kBAAA;EACA,mBAAA;EACA,qBAAA;ClB20ED;AkBz0ED;;;EAGE,YAAA;EACA,aAAA;EACA,kBAAA;ClB20ED;AkBz0ED;;;EAGE,YAAA;EACA,aAAA;EACA,kBAAA;ClB20ED;AkBv0ED;;;;;;;;;;ECpZI,eAAA;CnBuuFH;AkBn1ED;EChZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CLwrFT;AmBtuFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CL6rFT;AkB71ED;ECtYI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBsuFH;AkBl2ED;EChYI,eAAA;CnBquFH;AkBl2ED;;;;;;;;;;ECvZI,eAAA;CnBqwFH;AkB92ED;ECnZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CLstFT;AmBpwFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CL2tFT;AkBx3ED;ECzYI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBowFH;AkB73ED;ECnYI,eAAA;CnBmwFH;AkB73ED;;;;;;;;;;EC1ZI,eAAA;CnBmyFH;AkBz4ED;ECtZI,sBAAA;Ed+CF,yDAAA;EACQ,iDAAA;CLovFT;AmBlyFG;EACE,sBAAA;Ed4CJ,0EAAA;EACQ,kEAAA;CLyvFT;AkBn5ED;EC5YI,eAAA;EACA,sBAAA;EACA,0BAAA;CnBkyFH;AkBx5ED;ECtYI,eAAA;CnBiyFH;AkBp5EC;EACG,UAAA;ClBs5EJ;AkBp5EC;EACG,OAAA;ClBs5EJ;AkB54ED;EACE,eAAA;EACA,gBAAA;EACA,oBAAA;EACA,eAAA;ClB84ED;AkB3zED;EAAA;IA9DM,sBAAA;IACA,iBAAA;IACA,uBAAA;GlB63EH;EkBj0EH;IAvDM,sBAAA;IACA,YAAA;IACA,uBAAA;GlB23EH;EkBt0EH;IAhDM,sBAAA;GlBy3EH;EkBz0EH;IA5CM,sBAAA;IACA,uBAAA;GlBw3EH;EkB70EH;;;IAtCQ,YAAA;GlBw3EL;EkBl1EH;IAhCM,YAAA;GlBq3EH;EkBr1EH;IA5BM,iBAAA;IACA,uBAAA;GlBo3EH;EkBz1EH;;IApBM,sBAAA;IACA,cAAA;IACA,iBAAA;IACA,uBAAA;GlBi3EH;EkBh2EH;;IAdQ,gBAAA;GlBk3EL;EkBp2EH;;IATM,mBAAA;IACA,eAAA;GlBi3EH;EkBz2EH;IAHM,OAAA;GlB+2EH;CACF;AkBr2ED;;;;EASI,cAAA;EACA,iBAAA;EACA,iBAAA;ClBk2EH;AkB72ED;;EAiBI,iBAAA;ClBg2EH;AkBj3ED;EJhhBE,mBAAA;EACA,oBAAA;Cdo4FD;AkB90EC;EAAA;IAVI,kBAAA;IACA,iBAAA;IACA,iBAAA;GlB41EH;CACF;AkB53ED;EAwCI,YAAA;ClBu1EH;AkBz0EC;EAAA;IAJM,yBAAA;IACA,gBAAA;GlBi1EL;CACF;AkBv0EC;EAAA;IAJM,iBAAA;IACA,gBAAA;GlB+0EL;CACF;AoBl6FD;EACE,sBAAA;EACA,iBAAA;EACA,oBAAA;EACA,mBAAA;EACA,uBAAA;EACA,+BAAA;MAAA,2BAAA;EACA,gBAAA;EACA,uBAAA;EACA,8BAAA;EACA,oBAAA;EC6CA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,mBAAA;EhB4JA,0BAAA;EACG,uBAAA;EACC,sBAAA;EACI,kBAAA;CL6tFT;AoBr6FG;;;;;;EdrBF,qBAAA;EAEA,2CAAA;EACA,qBAAA;CNi8FD;AoBz6FC;;;EAGE,eAAA;EACA,sBAAA;CpB26FH;AoBx6FC;;EAEE,WAAA;EACA,uBAAA;Ef2BF,yDAAA;EACQ,iDAAA;CLg5FT;AoBx6FC;;;EAGE,oBAAA;EE7CF,cAAA;EAGA,0BAAA;EjB8DA,yBAAA;EACQ,iBAAA;CLy5FT;AoBx6FG;;EAEE,qBAAA;CpB06FL;AoBj6FD;EC3DE,eAAA;EACA,0BAAA;EACA,sBAAA;CrB+9FD;AqB79FC;;EAEE,eAAA;EACA,0BAAA;EACI,sBAAA;CrB+9FP;AqB79FC;EACE,eAAA;EACA,0BAAA;EACI,sBAAA;CrB+9FP;AqB79FC;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrB+9FP;AqB79FG;;;;;;;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBq+FT;AqBl+FC;;;EAGE,uBAAA;CrBo+FH;AqB/9FG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACI,sBAAA;CrB6+FT;AoB/9FD;ECTI,eAAA;EACA,0BAAA;CrB2+FH;AoBh+FD;EC9DE,eAAA;EACA,0BAAA;EACA,sBAAA;CrBiiGD;AqB/hGC;;EAEE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBiiGP;AqB/hGC;EACE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBiiGP;AqB/hGC;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBiiGP;AqB/hGG;;;;;;;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBuiGT;AqBpiGC;;;EAGE,uBAAA;CrBsiGH;AqBjiGG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACI,sBAAA;CrB+iGT;AoB9hGD;ECZI,eAAA;EACA,0BAAA;CrB6iGH;AoB9hGD;EClEE,eAAA;EACA,0BAAA;EACA,sBAAA;CrBmmGD;AqBjmGC;;EAEE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBmmGP;AqBjmGC;EACE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBmmGP;AqBjmGC;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBmmGP;AqBjmGG;;;;;;;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBymGT;AqBtmGC;;;EAGE,uBAAA;CrBwmGH;AqBnmGG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACI,sBAAA;CrBinGT;AoB5lGD;EChBI,eAAA;EACA,0BAAA;CrB+mGH;AoB5lGD;ECtEE,eAAA;EACA,0BAAA;EACA,sBAAA;CrBqqGD;AqBnqGC;;EAEE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBqqGP;AqBnqGC;EACE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBqqGP;AqBnqGC;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBqqGP;AqBnqGG;;;;;;;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrB2qGT;AqBxqGC;;;EAGE,uBAAA;CrB0qGH;AqBrqGG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACI,sBAAA;CrBmrGT;AoB1pGD;ECpBI,eAAA;EACA,0BAAA;CrBirGH;AoB1pGD;EC1EE,eAAA;EACA,0BAAA;EACA,sBAAA;CrBuuGD;AqBruGC;;EAEE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBuuGP;AqBruGC;EACE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBuuGP;AqBruGC;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrBuuGP;AqBruGG;;;;;;;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrB6uGT;AqB1uGC;;;EAGE,uBAAA;CrB4uGH;AqBvuGG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACI,sBAAA;CrBqvGT;AoBxtGD;ECxBI,eAAA;EACA,0BAAA;CrBmvGH;AoBxtGD;EC9EE,eAAA;EACA,0BAAA;EACA,sBAAA;CrByyGD;AqBvyGC;;EAEE,eAAA;EACA,0BAAA;EACI,sBAAA;CrByyGP;AqBvyGC;EACE,eAAA;EACA,0BAAA;EACI,sBAAA;CrByyGP;AqBvyGC;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrByyGP;AqBvyGG;;;;;;;;;EAGE,eAAA;EACA,0BAAA;EACI,sBAAA;CrB+yGT;AqB5yGC;;;EAGE,uBAAA;CrB8yGH;AqBzyGG;;;;;;;;;;;;;;;;;;EAME,0BAAA;EACI,sBAAA;CrBuzGT;AoBtxGD;EC5BI,eAAA;EACA,0BAAA;CrBqzGH;AoBjxGD;EACE,eAAA;EACA,oBAAA;EACA,iBAAA;CpBmxGD;AoBjxGC;;;;;EAKE,8BAAA;EfnCF,yBAAA;EACQ,iBAAA;CLuzGT;AoBlxGC;;;;EAIE,0BAAA;CpBoxGH;AoBlxGC;;EAEE,eAAA;EACA,2BAAA;EACA,8BAAA;CpBoxGH;AoBhxGG;;;;EAEE,eAAA;EACA,sBAAA;CpBoxGL;AoB3wGD;;ECrEE,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CrBo1GD;AoB9wGD;;ECzEE,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CrB21GD;AoBjxGD;;EC7EE,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CrBk2GD;AoBhxGD;EACE,eAAA;EACA,YAAA;CpBkxGD;AoB9wGD;EACE,gBAAA;CpBgxGD;AoBzwGC;;;EACE,YAAA;CpB6wGH;AuBv6GD;EACE,WAAA;ElBoLA,yCAAA;EACK,oCAAA;EACG,iCAAA;CLsvGT;AuB16GC;EACE,WAAA;CvB46GH;AuBx6GD;EACE,cAAA;CvB06GD;AuBx6GC;EAAY,eAAA;CvB26Gb;AuB16GC;EAAY,mBAAA;CvB66Gb;AuB56GC;EAAY,yBAAA;CvB+6Gb;AuB56GD;EACE,mBAAA;EACA,UAAA;EACA,iBAAA;ElBuKA,gDAAA;EACQ,2CAAA;KAAA,wCAAA;EAOR,mCAAA;EACQ,8BAAA;KAAA,2BAAA;EAGR,yCAAA;EACQ,oCAAA;KAAA,iCAAA;CLgwGT;AwB18GD;EACE,sBAAA;EACA,SAAA;EACA,UAAA;EACA,iBAAA;EACA,uBAAA;EACA,uBAAA;EACA,yBAAA;EACA,oCAAA;EACA,mCAAA;CxB48GD;AwBx8GD;;EAEE,mBAAA;CxB08GD;AwBt8GD;EACE,WAAA;CxBw8GD;AwBp8GD;EACE,mBAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,YAAA;EACA,iBAAA;EACA,eAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,iBAAA;EACA,0BAAA;EACA,0BAAA;EACA,sCAAA;EACA,mBAAA;EnBsBA,oDAAA;EACQ,4CAAA;EmBrBR,qCAAA;UAAA,6BAAA;CxBu8GD;AwBl8GC;EACE,SAAA;EACA,WAAA;CxBo8GH;AwB79GD;ECzBE,YAAA;EACA,cAAA;EACA,iBAAA;EACA,0BAAA;CzBy/GD;AwBn+GD;EAmCI,eAAA;EACA,kBAAA;EACA,YAAA;EACA,oBAAA;EACA,wBAAA;EACA,eAAA;EACA,oBAAA;CxBm8GH;AwB77GC;;EAEE,sBAAA;EACA,eAAA;EACA,0BAAA;CxB+7GH;AwBz7GC;;;EAGE,eAAA;EACA,sBAAA;EACA,WAAA;EACA,0BAAA;CxB27GH;AwBl7GC;;;EAGE,eAAA;CxBo7GH;AwBh7GC;;EAEE,sBAAA;EACA,8BAAA;EACA,uBAAA;EE3GF,oEAAA;EF6GE,oBAAA;CxBk7GH;AwB76GD;EAGI,eAAA;CxB66GH;AwBh7GD;EAQI,WAAA;CxB26GH;AwBn6GD;EACE,WAAA;EACA,SAAA;CxBq6GD;AwB75GD;EACE,QAAA;EACA,YAAA;CxB+5GD;AwB35GD;EACE,eAAA;EACA,kBAAA;EACA,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,oBAAA;CxB65GD;AwBz5GD;EACE,gBAAA;EACA,QAAA;EACA,SAAA;EACA,UAAA;EACA,OAAA;EACA,aAAA;CxB25GD;AwBv5GD;EACE,SAAA;EACA,WAAA;CxBy5GD;AwBj5GD;;EAII,cAAA;EACA,0BAAA;EACA,4BAAA;EACA,YAAA;CxBi5GH;AwBx5GD;;EAWI,UAAA;EACA,aAAA;EACA,mBAAA;CxBi5GH;AwB53GD;EAXE;IApEA,WAAA;IACA,SAAA;GxB+8GC;EwB54GD;IA1DA,QAAA;IACA,YAAA;GxBy8GC;CACF;A2BzlHD;;EAEE,mBAAA;EACA,sBAAA;EACA,uBAAA;C3B2lHD;A2B/lHD;;EAMI,mBAAA;EACA,YAAA;C3B6lHH;A2B3lHG;;;;;;;;EAIE,WAAA;C3BimHL;A2B3lHD;;;;EAKI,kBAAA;C3B4lHH;A2BvlHD;EACE,kBAAA;C3BylHD;A2B1lHD;;;EAOI,YAAA;C3BwlHH;A2B/lHD;;;EAYI,iBAAA;C3BwlHH;A2BplHD;EACE,iBAAA;C3BslHD;A2BllHD;EACE,eAAA;C3BolHD;A2BnlHC;EClDA,8BAAA;EACG,2BAAA;C5BwoHJ;A2BllHD;;EC/CE,6BAAA;EACG,0BAAA;C5BqoHJ;A2BjlHD;EACE,YAAA;C3BmlHD;A2BjlHD;EACE,iBAAA;C3BmlHD;A2BjlHD;;ECnEE,8BAAA;EACG,2BAAA;C5BwpHJ;A2BhlHD;ECjEE,6BAAA;EACG,0BAAA;C5BopHJ;A2B/kHD;;EAEE,WAAA;C3BilHD;A2BhkHD;EACE,kBAAA;EACA,mBAAA;C3BkkHD;A2BhkHD;EACE,mBAAA;EACA,oBAAA;C3BkkHD;A2B7jHD;EtB/CE,yDAAA;EACQ,iDAAA;CL+mHT;A2B7jHC;EtBnDA,yBAAA;EACQ,iBAAA;CLmnHT;A2B1jHD;EACE,eAAA;C3B4jHD;A2BzjHD;EACE,wBAAA;EACA,uBAAA;C3B2jHD;A2BxjHD;EACE,wBAAA;C3B0jHD;A2BnjHD;;;EAII,eAAA;EACA,YAAA;EACA,YAAA;EACA,gBAAA;C3BojHH;A2B3jHD;EAcM,YAAA;C3BgjHL;A2B9jHD;;;;EAsBI,iBAAA;EACA,eAAA;C3B8iHH;A2BziHC;EACE,iBAAA;C3B2iHH;A2BziHC;EACE,6BAAA;ECpKF,8BAAA;EACC,6BAAA;C5BgtHF;A2B1iHC;EACE,+BAAA;EChLF,2BAAA;EACC,0BAAA;C5B6tHF;A2B1iHD;EACE,iBAAA;C3B4iHD;A2B1iHD;;EC/KE,8BAAA;EACC,6BAAA;C5B6tHF;A2BziHD;EC7LE,2BAAA;EACC,0BAAA;C5ByuHF;A2BriHD;EACE,eAAA;EACA,YAAA;EACA,oBAAA;EACA,0BAAA;C3BuiHD;A2B3iHD;;EAOI,YAAA;EACA,oBAAA;EACA,UAAA;C3BwiHH;A2BjjHD;EAYI,YAAA;C3BwiHH;A2BpjHD;EAgBI,WAAA;C3BuiHH;A2BthHD;;;;EAKM,mBAAA;EACA,uBAAA;EACA,qBAAA;C3BuhHL;A6BjwHD;EACE,mBAAA;EACA,eAAA;EACA,0BAAA;C7BmwHD;A6BhwHC;EACE,YAAA;EACA,gBAAA;EACA,iBAAA;C7BkwHH;A6B3wHD;EAeI,mBAAA;EACA,WAAA;EAKA,YAAA;EAEA,YAAA;EACA,iBAAA;C7B0vHH;A6BjvHD;;;EV8BE,aAAA;EACA,mBAAA;EACA,gBAAA;EACA,uBAAA;EACA,mBAAA;CnBwtHD;AmBttHC;;;EACE,aAAA;EACA,kBAAA;CnB0tHH;AmBvtHC;;;;;;EAEE,aAAA;CnB6tHH;A6BnwHD;;;EVyBE,aAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;CnB+uHD;AmB7uHC;;;EACE,aAAA;EACA,kBAAA;CnBivHH;AmB9uHC;;;;;;EAEE,aAAA;CnBovHH;A6BjxHD;;;EAGE,oBAAA;C7BmxHD;A6BjxHC;;;EACE,iBAAA;C7BqxHH;A6BjxHD;;EAEE,UAAA;EACA,oBAAA;EACA,uBAAA;C7BmxHD;A6B9wHD;EACE,kBAAA;EACA,gBAAA;EACA,oBAAA;EACA,eAAA;EACA,eAAA;EACA,mBAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;C7BgxHD;A6B7wHC;EACE,kBAAA;EACA,gBAAA;EACA,mBAAA;C7B+wHH;A6B7wHC;EACE,mBAAA;EACA,gBAAA;EACA,mBAAA;C7B+wHH;A6BnyHD;;EA0BI,cAAA;C7B6wHH;A6BxwHD;;;;;;;EDhGE,8BAAA;EACG,2BAAA;C5Bi3HJ;A6BzwHD;EACE,gBAAA;C7B2wHD;A6BzwHD;;;;;;;EDpGE,6BAAA;EACG,0BAAA;C5Bs3HJ;A6B1wHD;EACE,eAAA;C7B4wHD;A6BvwHD;EACE,mBAAA;EAGA,aAAA;EACA,oBAAA;C7BuwHD;A6B5wHD;EAUI,mBAAA;C7BqwHH;A6B/wHD;EAYM,kBAAA;C7BswHL;A6BnwHG;;;EAGE,WAAA;C7BqwHL;A6BhwHC;;EAGI,mBAAA;C7BiwHL;A6B9vHC;;EAGI,WAAA;EACA,kBAAA;C7B+vHL;A8B15HD;EACE,iBAAA;EACA,gBAAA;EACA,iBAAA;C9B45HD;A8B/5HD;EAOI,mBAAA;EACA,eAAA;C9B25HH;A8Bn6HD;EAWM,mBAAA;EACA,eAAA;EACA,mBAAA;C9B25HL;A8B15HK;;EAEE,sBAAA;EACA,0BAAA;C9B45HP;A8Bv5HG;EACE,eAAA;C9By5HL;A8Bv5HK;;EAEE,eAAA;EACA,sBAAA;EACA,8BAAA;EACA,oBAAA;C9By5HP;A8Bl5HG;;;EAGE,0BAAA;EACA,sBAAA;C9Bo5HL;A8B77HD;ELHE,YAAA;EACA,cAAA;EACA,iBAAA;EACA,0BAAA;CzBm8HD;A8Bn8HD;EA0DI,gBAAA;C9B44HH;A8Bn4HD;EACE,iCAAA;C9Bq4HD;A8Bt4HD;EAGI,YAAA;EAEA,oBAAA;C9Bq4HH;A8B14HD;EASM,kBAAA;EACA,wBAAA;EACA,8BAAA;EACA,2BAAA;C9Bo4HL;A8Bn4HK;EACE,sCAAA;C9Bq4HP;A8B/3HK;;;EAGE,eAAA;EACA,0BAAA;EACA,0BAAA;EACA,iCAAA;EACA,gBAAA;C9Bi4HP;A8B53HC;EAqDA,YAAA;EA8BA,iBAAA;C9B6yHD;A8Bh4HC;EAwDE,YAAA;C9B20HH;A8Bn4HC;EA0DI,mBAAA;EACA,mBAAA;C9B40HL;A8Bv4HC;EAgEE,UAAA;EACA,WAAA;C9B00HH;A8B9zHD;EAAA;IAPM,oBAAA;IACA,UAAA;G9By0HH;E8Bn0HH;IAJQ,iBAAA;G9B00HL;CACF;A8Bp5HC;EAuFE,gBAAA;EACA,mBAAA;C9Bg0HH;A8Bx5HC;;;EA8FE,0BAAA;C9B+zHH;A8BjzHD;EAAA;IATM,iCAAA;IACA,2BAAA;G9B8zHH;E8BtzHH;;;IAHM,6BAAA;G9B8zHH;CACF;A8B/5HD;EAEI,YAAA;C9Bg6HH;A8Bl6HD;EAMM,mBAAA;C9B+5HL;A8Br6HD;EASM,iBAAA;C9B+5HL;A8B15HK;;;EAGE,eAAA;EACA,0BAAA;C9B45HP;A8Bp5HD;EAEI,YAAA;C9Bq5HH;A8Bv5HD;EAIM,gBAAA;EACA,eAAA;C9Bs5HL;A8B14HD;EACE,YAAA;C9B44HD;A8B74HD;EAII,YAAA;C9B44HH;A8Bh5HD;EAMM,mBAAA;EACA,mBAAA;C9B64HL;A8Bp5HD;EAYI,UAAA;EACA,WAAA;C9B24HH;A8B/3HD;EAAA;IAPM,oBAAA;IACA,UAAA;G9B04HH;E8Bp4HH;IAJQ,iBAAA;G9B24HL;CACF;A8Bn4HD;EACE,iBAAA;C9Bq4HD;A8Bt4HD;EAKI,gBAAA;EACA,mBAAA;C9Bo4HH;A8B14HD;;;EAYI,0BAAA;C9Bm4HH;A8Br3HD;EAAA;IATM,iCAAA;IACA,2BAAA;G9Bk4HH;E8B13HH;;;IAHM,6BAAA;G9Bk4HH;CACF;A8Bz3HD;EAEI,cAAA;C9B03HH;A8B53HD;EAKI,eAAA;C9B03HH;A8Bj3HD;EAEE,iBAAA;EF3OA,2BAAA;EACC,0BAAA;C5B8lIF;A+BxlID;EACE,mBAAA;EACA,iBAAA;EACA,oBAAA;EACA,8BAAA;C/B0lID;A+BllID;EAAA;IAFI,mBAAA;G/BwlID;CACF;A+BzkID;EAAA;IAFI,YAAA;G/B+kID;CACF;A+BjkID;EACE,oBAAA;EACA,oBAAA;EACA,mBAAA;EACA,kCAAA;EACA,2DAAA;UAAA,mDAAA;EAEA,kCAAA;C/BkkID;A+BhkIC;EACE,iBAAA;C/BkkIH;A+BtiID;EAAA;IAxBI,YAAA;IACA,cAAA;IACA,yBAAA;YAAA,iBAAA;G/BkkID;E+BhkIC;IACE,0BAAA;IACA,wBAAA;IACA,kBAAA;IACA,6BAAA;G/BkkIH;E+B/jIC;IACE,oBAAA;G/BikIH;E+B5jIC;;;IAGE,gBAAA;IACA,iBAAA;G/B8jIH;CACF;A+B1jID;;EAGI,kBAAA;C/B2jIH;A+BtjIC;EAAA;;IAFI,kBAAA;G/B6jIH;CACF;A+BpjID;;;;EAII,oBAAA;EACA,mBAAA;C/BsjIH;A+BhjIC;EAAA;;;;IAHI,gBAAA;IACA,eAAA;G/B0jIH;CACF;A+B9iID;EACE,cAAA;EACA,sBAAA;C/BgjID;A+B3iID;EAAA;IAFI,iBAAA;G/BijID;CACF;A+B7iID;;EAEE,gBAAA;EACA,SAAA;EACA,QAAA;EACA,cAAA;C/B+iID;A+BziID;EAAA;;IAFI,iBAAA;G/BgjID;CACF;A+B9iID;EACE,OAAA;EACA,sBAAA;C/BgjID;A+B9iID;EACE,UAAA;EACA,iBAAA;EACA,sBAAA;C/BgjID;A+B1iID;EACE,YAAA;EACA,mBAAA;EACA,gBAAA;EACA,kBAAA;EACA,aAAA;C/B4iID;A+B1iIC;;EAEE,sBAAA;C/B4iIH;A+BrjID;EAaI,eAAA;C/B2iIH;A+BliID;EALI;;IAEE,mBAAA;G/B0iIH;CACF;A+BhiID;EACE,mBAAA;EACA,aAAA;EACA,mBAAA;EACA,kBAAA;EC9LA,gBAAA;EACA,mBAAA;ED+LA,8BAAA;EACA,uBAAA;EACA,8BAAA;EACA,mBAAA;C/BmiID;A+B/hIC;EACE,WAAA;C/BiiIH;A+B/iID;EAmBI,eAAA;EACA,YAAA;EACA,YAAA;EACA,mBAAA;C/B+hIH;A+BrjID;EAyBI,gBAAA;C/B+hIH;A+BzhID;EAAA;IAFI,cAAA;G/B+hID;CACF;A+BthID;EACE,oBAAA;C/BwhID;A+BzhID;EAII,kBAAA;EACA,qBAAA;EACA,kBAAA;C/BwhIH;A+B5/HC;EAAA;IAtBI,iBAAA;IACA,YAAA;IACA,YAAA;IACA,cAAA;IACA,8BAAA;IACA,UAAA;IACA,yBAAA;YAAA,iBAAA;G/BshIH;E+BtgID;;IAbM,2BAAA;G/BuhIL;E+B1gID;IAVM,kBAAA;G/BuhIL;E+BthIK;;IAEE,uBAAA;G/BwhIP;CACF;A+BtgID;EAAA;IAXI,YAAA;IACA,UAAA;G/BqhID;E+B3gIH;IAPM,YAAA;G/BqhIH;E+B9gIH;IALQ,kBAAA;IACA,qBAAA;G/BshIL;CACF;A+B3gID;EACE,mBAAA;EACA,oBAAA;EACA,mBAAA;EACA,kCAAA;EACA,qCAAA;E1B9NA,6FAAA;EACQ,qFAAA;E2B/DR,gBAAA;EACA,mBAAA;ChC4yID;AkB5xHD;EAAA;IA9DM,sBAAA;IACA,iBAAA;IACA,uBAAA;GlB81HH;EkBlyHH;IAvDM,sBAAA;IACA,YAAA;IACA,uBAAA;GlB41HH;EkBvyHH;IAhDM,sBAAA;GlB01HH;EkB1yHH;IA5CM,sBAAA;IACA,uBAAA;GlBy1HH;EkB9yHH;;;IAtCQ,YAAA;GlBy1HL;EkBnzHH;IAhCM,YAAA;GlBs1HH;EkBtzHH;IA5BM,iBAAA;IACA,uBAAA;GlBq1HH;EkB1zHH;;IApBM,sBAAA;IACA,cAAA;IACA,iBAAA;IACA,uBAAA;GlBk1HH;EkBj0HH;;IAdQ,gBAAA;GlBm1HL;EkBr0HH;;IATM,mBAAA;IACA,eAAA;GlBk1HH;EkB10HH;IAHM,OAAA;GlBg1HH;CACF;A+BpjIC;EAAA;IANI,mBAAA;G/B8jIH;E+B5jIG;IACE,iBAAA;G/B8jIL;CACF;A+B7iID;EAAA;IARI,YAAA;IACA,UAAA;IACA,eAAA;IACA,gBAAA;IACA,eAAA;IACA,kBAAA;I1BzPF,yBAAA;IACQ,iBAAA;GLmzIP;CACF;A+BnjID;EACE,cAAA;EHpUA,2BAAA;EACC,0BAAA;C5B03IF;A+BnjID;EACE,iBAAA;EHzUA,6BAAA;EACC,4BAAA;EAOD,8BAAA;EACC,6BAAA;C5By3IF;A+B/iID;EChVE,gBAAA;EACA,mBAAA;ChCk4ID;A+BhjIC;ECnVA,iBAAA;EACA,oBAAA;ChCs4ID;A+BjjIC;ECtVA,iBAAA;EACA,oBAAA;ChC04ID;A+B3iID;EChWE,iBAAA;EACA,oBAAA;ChC84ID;A+BviID;EAAA;IAJI,YAAA;IACA,kBAAA;IACA,mBAAA;G/B+iID;CACF;A+BlhID;EAhBE;IExWA,uBAAA;GjC84IC;E+BriID;IE5WA,wBAAA;IF8WE,oBAAA;G/BuiID;E+BziID;IAKI,gBAAA;G/BuiIH;CACF;A+B9hID;EACE,0BAAA;EACA,sBAAA;C/BgiID;A+BliID;EAKI,eAAA;C/BgiIH;A+B/hIG;;EAEE,eAAA;EACA,8BAAA;C/BiiIL;A+B1iID;EAcI,eAAA;C/B+hIH;A+B7iID;EAmBM,eAAA;C/B6hIL;A+B3hIK;;EAEE,eAAA;EACA,8BAAA;C/B6hIP;A+BzhIK;;;EAGE,eAAA;EACA,0BAAA;C/B2hIP;A+BvhIK;;;EAGE,eAAA;EACA,8BAAA;C/ByhIP;A+BjkID;EA8CI,sBAAA;C/BshIH;A+BrhIG;;EAEE,0BAAA;C/BuhIL;A+BxkID;EAoDM,0BAAA;C/BuhIL;A+B3kID;;EA0DI,sBAAA;C/BqhIH;A+B9gIK;;;EAGE,0BAAA;EACA,eAAA;C/BghIP;A+B/+HC;EAAA;IAzBQ,eAAA;G/B4gIP;E+B3gIO;;IAEE,eAAA;IACA,8BAAA;G/B6gIT;E+BzgIO;;;IAGE,eAAA;IACA,0BAAA;G/B2gIT;E+BvgIO;;;IAGE,eAAA;IACA,8BAAA;G/BygIT;CACF;A+B3mID;EA8GI,eAAA;C/BggIH;A+B//HG;EACE,eAAA;C/BigIL;A+BjnID;EAqHI,eAAA;C/B+/HH;A+B9/HG;;EAEE,eAAA;C/BggIL;A+B5/HK;;;;EAEE,eAAA;C/BggIP;A+Bx/HD;EACE,0BAAA;EACA,sBAAA;C/B0/HD;A+B5/HD;EAKI,eAAA;C/B0/HH;A+Bz/HG;;EAEE,eAAA;EACA,8BAAA;C/B2/HL;A+BpgID;EAcI,eAAA;C/By/HH;A+BvgID;EAmBM,eAAA;C/Bu/HL;A+Br/HK;;EAEE,eAAA;EACA,8BAAA;C/Bu/HP;A+Bn/HK;;;EAGE,eAAA;EACA,0BAAA;C/Bq/HP;A+Bj/HK;;;EAGE,eAAA;EACA,8BAAA;C/Bm/HP;A+B3hID;EA+CI,sBAAA;C/B++HH;A+B9+HG;;EAEE,0BAAA;C/Bg/HL;A+BliID;EAqDM,0BAAA;C/Bg/HL;A+BriID;;EA2DI,sBAAA;C/B8+HH;A+Bx+HK;;;EAGE,0BAAA;EACA,eAAA;C/B0+HP;A+Bn8HC;EAAA;IA/BQ,sBAAA;G/Bs+HP;E+Bv8HD;IA5BQ,0BAAA;G/Bs+HP;E+B18HD;IAzBQ,eAAA;G/Bs+HP;E+Br+HO;;IAEE,eAAA;IACA,8BAAA;G/Bu+HT;E+Bn+HO;;;IAGE,eAAA;IACA,0BAAA;G/Bq+HT;E+Bj+HO;;;IAGE,eAAA;IACA,8BAAA;G/Bm+HT;CACF;A+B3kID;EA+GI,eAAA;C/B+9HH;A+B99HG;EACE,eAAA;C/Bg+HL;A+BjlID;EAsHI,eAAA;C/B89HH;A+B79HG;;EAEE,eAAA;C/B+9HL;A+B39HK;;;;EAEE,eAAA;C/B+9HP;AkCzmJD;EACE,kBAAA;EACA,oBAAA;EACA,iBAAA;EACA,0BAAA;EACA,mBAAA;ClC2mJD;AkChnJD;EAQI,sBAAA;ClC2mJH;AkCnnJD;EAWM,kBAAA;EACA,eAAA;EACA,eAAA;ClC2mJL;AkCxnJD;EAkBI,eAAA;ClCymJH;AmC7nJD;EACE,sBAAA;EACA,gBAAA;EACA,eAAA;EACA,mBAAA;CnC+nJD;AmCnoJD;EAOI,gBAAA;CnC+nJH;AmCtoJD;;EAUM,mBAAA;EACA,YAAA;EACA,kBAAA;EACA,wBAAA;EACA,sBAAA;EACA,eAAA;EACA,0BAAA;EACA,0BAAA;EACA,kBAAA;CnCgoJL;AmC9nJG;;EAGI,eAAA;EPXN,+BAAA;EACG,4BAAA;C5B2oJJ;AmC7nJG;;EPvBF,gCAAA;EACG,6BAAA;C5BwpJJ;AmCxnJG;;;;EAEE,WAAA;EACA,eAAA;EACA,0BAAA;EACA,sBAAA;CnC4nJL;AmCtnJG;;;;;;EAGE,WAAA;EACA,eAAA;EACA,0BAAA;EACA,sBAAA;EACA,gBAAA;CnC2nJL;AmClrJD;;;;;;EAkEM,eAAA;EACA,0BAAA;EACA,sBAAA;EACA,oBAAA;CnCwnJL;AmC/mJD;;EC3EM,mBAAA;EACA,gBAAA;EACA,uBAAA;CpC8rJL;AoC5rJG;;ERKF,+BAAA;EACG,4BAAA;C5B2rJJ;AoC3rJG;;ERTF,gCAAA;EACG,6BAAA;C5BwsJJ;AmC1nJD;;EChFM,kBAAA;EACA,gBAAA;EACA,iBAAA;CpC8sJL;AoC5sJG;;ERKF,+BAAA;EACG,4BAAA;C5B2sJJ;AoC3sJG;;ERTF,gCAAA;EACG,6BAAA;C5BwtJJ;AqC3tJD;EACE,gBAAA;EACA,eAAA;EACA,iBAAA;EACA,mBAAA;CrC6tJD;AqCjuJD;EAOI,gBAAA;CrC6tJH;AqCpuJD;;EAUM,sBAAA;EACA,kBAAA;EACA,0BAAA;EACA,0BAAA;EACA,oBAAA;CrC8tJL;AqC5uJD;;EAmBM,sBAAA;EACA,0BAAA;CrC6tJL;AqCjvJD;;EA2BM,aAAA;CrC0tJL;AqCrvJD;;EAkCM,YAAA;CrCutJL;AqCzvJD;;;;EA2CM,eAAA;EACA,0BAAA;EACA,oBAAA;CrCotJL;AsClwJD;EACE,gBAAA;EACA,wBAAA;EACA,eAAA;EACA,kBAAA;EACA,eAAA;EACA,eAAA;EACA,mBAAA;EACA,oBAAA;EACA,yBAAA;EACA,qBAAA;CtCowJD;AsChwJG;;EAEE,eAAA;EACA,sBAAA;EACA,gBAAA;CtCkwJL;AsC7vJC;EACE,cAAA;CtC+vJH;AsC3vJC;EACE,mBAAA;EACA,UAAA;CtC6vJH;AsCtvJD;ECtCE,0BAAA;CvC+xJD;AuC5xJG;;EAEE,0BAAA;CvC8xJL;AsCzvJD;EC1CE,0BAAA;CvCsyJD;AuCnyJG;;EAEE,0BAAA;CvCqyJL;AsC5vJD;EC9CE,0BAAA;CvC6yJD;AuC1yJG;;EAEE,0BAAA;CvC4yJL;AsC/vJD;EClDE,0BAAA;CvCozJD;AuCjzJG;;EAEE,0BAAA;CvCmzJL;AsClwJD;ECtDE,0BAAA;CvC2zJD;AuCxzJG;;EAEE,0BAAA;CvC0zJL;AsCrwJD;EC1DE,0BAAA;CvCk0JD;AuC/zJG;;EAEE,0BAAA;CvCi0JL;AwCn0JD;EACE,sBAAA;EACA,gBAAA;EACA,iBAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,eAAA;EACA,uBAAA;EACA,oBAAA;EACA,mBAAA;EACA,0BAAA;EACA,oBAAA;CxCq0JD;AwCl0JC;EACE,cAAA;CxCo0JH;AwCh0JC;EACE,mBAAA;EACA,UAAA;CxCk0JH;AwC/zJC;;EAEE,OAAA;EACA,iBAAA;CxCi0JH;AwC5zJG;;EAEE,eAAA;EACA,sBAAA;EACA,gBAAA;CxC8zJL;AwCzzJC;;EAEE,eAAA;EACA,0BAAA;CxC2zJH;AwCxzJC;EACE,aAAA;CxC0zJH;AwCvzJC;EACE,kBAAA;CxCyzJH;AwCtzJC;EACE,iBAAA;CxCwzJH;AyCl3JD;EACE,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,eAAA;EACA,0BAAA;CzCo3JD;AyCz3JD;;EASI,eAAA;CzCo3JH;AyC73JD;EAaI,oBAAA;EACA,gBAAA;EACA,iBAAA;CzCm3JH;AyCl4JD;EAmBI,0BAAA;CzCk3JH;AyC/2JC;;EAEE,mBAAA;CzCi3JH;AyCz4JD;EA4BI,gBAAA;CzCg3JH;AyC91JD;EAAA;IAdI,kBAAA;IACA,qBAAA;GzCg3JD;EyC92JC;;IAEE,mBAAA;IACA,oBAAA;GzCg3JH;EyCx2JH;;IAHM,gBAAA;GzC+2JH;CACF;A0C15JD;EACE,eAAA;EACA,aAAA;EACA,oBAAA;EACA,wBAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;ErCiLA,4CAAA;EACK,uCAAA;EACG,oCAAA;CL4uJT;A0Ct6JD;;EAaI,kBAAA;EACA,mBAAA;C1C65JH;A0Cz5JC;;;EAGE,sBAAA;C1C25JH;A0Ch7JD;EA0BI,aAAA;EACA,eAAA;C1Cy5JH;A2Cl7JD;EACE,cAAA;EACA,oBAAA;EACA,8BAAA;EACA,mBAAA;C3Co7JD;A2Cx7JD;EAQI,cAAA;EAEA,eAAA;C3Ck7JH;A2C57JD;EAeI,kBAAA;C3Cg7JH;A2C/7JD;;EAqBI,iBAAA;C3C86JH;A2Cn8JD;EAyBI,gBAAA;C3C66JH;A2Cr6JD;;EAEE,oBAAA;C3Cu6JD;A2Cz6JD;;EAMI,mBAAA;EACA,UAAA;EACA,aAAA;EACA,eAAA;C3Cu6JH;A2C/5JD;ECvDE,0BAAA;EACA,sBAAA;EACA,eAAA;C5Cy9JD;A2Cp6JD;EClDI,0BAAA;C5Cy9JH;A2Cv6JD;EC/CI,eAAA;C5Cy9JH;A2Ct6JD;EC3DE,0BAAA;EACA,sBAAA;EACA,eAAA;C5Co+JD;A2C36JD;ECtDI,0BAAA;C5Co+JH;A2C96JD;ECnDI,eAAA;C5Co+JH;A2C76JD;EC/DE,0BAAA;EACA,sBAAA;EACA,eAAA;C5C++JD;A2Cl7JD;EC1DI,0BAAA;C5C++JH;A2Cr7JD;ECvDI,eAAA;C5C++JH;A2Cp7JD;ECnEE,0BAAA;EACA,sBAAA;EACA,eAAA;C5C0/JD;A2Cz7JD;EC9DI,0BAAA;C5C0/JH;A2C57JD;EC3DI,eAAA;C5C0/JH;A6C5/JD;EACE;IAAQ,4BAAA;G7C+/JP;E6C9/JD;IAAQ,yBAAA;G7CigKP;CACF;A6C9/JD;EACE;IAAQ,4BAAA;G7CigKP;E6ChgKD;IAAQ,yBAAA;G7CmgKP;CACF;A6CtgKD;EACE;IAAQ,4BAAA;G7CigKP;E6ChgKD;IAAQ,yBAAA;G7CmgKP;CACF;A6C5/JD;EACE,iBAAA;EACA,aAAA;EACA,oBAAA;EACA,0BAAA;EACA,mBAAA;ExCsCA,uDAAA;EACQ,+CAAA;CLy9JT;A6C3/JD;EACE,YAAA;EACA,UAAA;EACA,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,mBAAA;EACA,0BAAA;ExCyBA,uDAAA;EACQ,+CAAA;EAyHR,oCAAA;EACK,+BAAA;EACG,4BAAA;CL62JT;A6Cx/JD;;ECCI,8MAAA;EACA,yMAAA;EACA,sMAAA;EDAF,mCAAA;UAAA,2BAAA;C7C4/JD;A6Cr/JD;;ExC5CE,2DAAA;EACK,sDAAA;EACG,mDAAA;CLqiKT;A6Cl/JD;EErEE,0BAAA;C/C0jKD;A+CvjKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9C0gKH;A6Ct/JD;EEzEE,0BAAA;C/CkkKD;A+C/jKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9CkhKH;A6C1/JD;EE7EE,0BAAA;C/C0kKD;A+CvkKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9C0hKH;A6C9/JD;EEjFE,0BAAA;C/CklKD;A+C/kKC;EDgDE,8MAAA;EACA,yMAAA;EACA,sMAAA;C9CkiKH;AgD1lKD;EAEE,iBAAA;ChD2lKD;AgDzlKC;EACE,cAAA;ChD2lKH;AgDvlKD;;EAEE,QAAA;EACA,iBAAA;ChDylKD;AgDtlKD;EACE,eAAA;ChDwlKD;AgDrlKD;EACE,eAAA;ChDulKD;AgDplKC;EACE,gBAAA;ChDslKH;AgDllKD;;EAEE,mBAAA;ChDolKD;AgDjlKD;;EAEE,oBAAA;ChDmlKD;AgDhlKD;;;EAGE,oBAAA;EACA,oBAAA;ChDklKD;AgD/kKD;EACE,uBAAA;ChDilKD;AgD9kKD;EACE,uBAAA;ChDglKD;AgD5kKD;EACE,cAAA;EACA,mBAAA;ChD8kKD;AgDxkKD;EACE,gBAAA;EACA,iBAAA;ChD0kKD;AiDjoKD;EAEE,oBAAA;EACA,gBAAA;CjDkoKD;AiD1nKD;EACE,mBAAA;EACA,eAAA;EACA,mBAAA;EAEA,oBAAA;EACA,0BAAA;EACA,0BAAA;CjD2nKD;AiDxnKC;ErB3BA,6BAAA;EACC,4BAAA;C5BspKF;AiDznKC;EACE,iBAAA;ErBvBF,gCAAA;EACC,+BAAA;C5BmpKF;AiDlnKD;;EAEE,eAAA;CjDonKD;AiDtnKD;;EAKI,eAAA;CjDqnKH;AiDjnKC;;;;EAEE,sBAAA;EACA,eAAA;EACA,0BAAA;CjDqnKH;AiDjnKD;EACE,YAAA;EACA,iBAAA;CjDmnKD;AiD9mKC;;;EAGE,0BAAA;EACA,eAAA;EACA,oBAAA;CjDgnKH;AiDrnKC;;;EASI,eAAA;CjDinKL;AiD1nKC;;;EAYI,eAAA;CjDmnKL;AiD9mKC;;;EAGE,WAAA;EACA,eAAA;EACA,0BAAA;EACA,sBAAA;CjDgnKH;AiDtnKC;;;;;;;;;EAYI,eAAA;CjDqnKL;AiDjoKC;;;EAeI,eAAA;CjDunKL;AkDztKC;EACE,eAAA;EACA,0BAAA;ClD2tKH;AkDztKG;;EAEE,eAAA;ClD2tKL;AkD7tKG;;EAKI,eAAA;ClD4tKP;AkDztKK;;;;EAEE,eAAA;EACA,0BAAA;ClD6tKP;AkD3tKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClDguKP;AkDtvKC;EACE,eAAA;EACA,0BAAA;ClDwvKH;AkDtvKG;;EAEE,eAAA;ClDwvKL;AkD1vKG;;EAKI,eAAA;ClDyvKP;AkDtvKK;;;;EAEE,eAAA;EACA,0BAAA;ClD0vKP;AkDxvKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClD6vKP;AkDnxKC;EACE,eAAA;EACA,0BAAA;ClDqxKH;AkDnxKG;;EAEE,eAAA;ClDqxKL;AkDvxKG;;EAKI,eAAA;ClDsxKP;AkDnxKK;;;;EAEE,eAAA;EACA,0BAAA;ClDuxKP;AkDrxKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClD0xKP;AkDhzKC;EACE,eAAA;EACA,0BAAA;ClDkzKH;AkDhzKG;;EAEE,eAAA;ClDkzKL;AkDpzKG;;EAKI,eAAA;ClDmzKP;AkDhzKK;;;;EAEE,eAAA;EACA,0BAAA;ClDozKP;AkDlzKK;;;;;;EAGE,YAAA;EACA,0BAAA;EACA,sBAAA;ClDuzKP;AiDttKD;EACE,cAAA;EACA,mBAAA;CjDwtKD;AiDttKD;EACE,iBAAA;EACA,iBAAA;CjDwtKD;AmDl1KD;EACE,oBAAA;EACA,0BAAA;EACA,8BAAA;EACA,mBAAA;E9C0DA,kDAAA;EACQ,0CAAA;CL2xKT;AmDj1KD;EACE,cAAA;CnDm1KD;AmD90KD;EACE,mBAAA;EACA,qCAAA;EvBpBA,6BAAA;EACC,4BAAA;C5Bq2KF;AmDp1KD;EAMI,eAAA;CnDi1KH;AmD50KD;EACE,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,eAAA;CnD80KD;AmDl1KD;;;;;EAWI,eAAA;CnD80KH;AmDz0KD;EACE,mBAAA;EACA,0BAAA;EACA,8BAAA;EvBxCA,gCAAA;EACC,+BAAA;C5Bo3KF;AmDn0KD;;EAGI,iBAAA;CnDo0KH;AmDv0KD;;EAMM,oBAAA;EACA,iBAAA;CnDq0KL;AmDj0KG;;EAEI,cAAA;EvBvEN,6BAAA;EACC,4BAAA;C5B24KF;AmD/zKG;;EAEI,iBAAA;EvBvEN,gCAAA;EACC,+BAAA;C5By4KF;AmDx1KD;EvB1DE,2BAAA;EACC,0BAAA;C5Bq5KF;AmD3zKD;EAEI,oBAAA;CnD4zKH;AmDzzKD;EACE,oBAAA;CnD2zKD;AmDnzKD;;;EAII,iBAAA;CnDozKH;AmDxzKD;;;EAOM,mBAAA;EACA,oBAAA;CnDszKL;AmD9zKD;;EvBzGE,6BAAA;EACC,4BAAA;C5B26KF;AmDn0KD;;;;EAmBQ,4BAAA;EACA,6BAAA;CnDszKP;AmD10KD;;;;;;;;EAwBU,4BAAA;CnD4zKT;AmDp1KD;;;;;;;;EA4BU,6BAAA;CnDk0KT;AmD91KD;;EvBjGE,gCAAA;EACC,+BAAA;C5Bm8KF;AmDn2KD;;;;EAyCQ,+BAAA;EACA,gCAAA;CnDg0KP;AmD12KD;;;;;;;;EA8CU,+BAAA;CnDs0KT;AmDp3KD;;;;;;;;EAkDU,gCAAA;CnD40KT;AmD93KD;;;;EA2DI,8BAAA;CnDy0KH;AmDp4KD;;EA+DI,cAAA;CnDy0KH;AmDx4KD;;EAmEI,UAAA;CnDy0KH;AmD54KD;;;;;;;;;;;;EA0EU,eAAA;CnDg1KT;AmD15KD;;;;;;;;;;;;EA8EU,gBAAA;CnD01KT;AmDx6KD;;;;;;;;EAuFU,iBAAA;CnD21KT;AmDl7KD;;;;;;;;EAgGU,iBAAA;CnD41KT;AmD57KD;EAsGI,UAAA;EACA,iBAAA;CnDy1KH;AmD/0KD;EACE,oBAAA;CnDi1KD;AmDl1KD;EAKI,iBAAA;EACA,mBAAA;CnDg1KH;AmDt1KD;EASM,gBAAA;CnDg1KL;AmDz1KD;EAcI,iBAAA;CnD80KH;AmD51KD;;EAkBM,8BAAA;CnD80KL;AmDh2KD;EAuBI,cAAA;CnD40KH;AmDn2KD;EAyBM,iCAAA;CnD60KL;AmDt0KD;EC1PE,sBAAA;CpDmkLD;AoDjkLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDmkLH;AoDtkLC;EAMI,0BAAA;CpDmkLL;AoDzkLC;EASI,eAAA;EACA,0BAAA;CpDmkLL;AoDhkLC;EAEI,6BAAA;CpDikLL;AmDr1KD;EC7PE,sBAAA;CpDqlLD;AoDnlLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDqlLH;AoDxlLC;EAMI,0BAAA;CpDqlLL;AoD3lLC;EASI,eAAA;EACA,0BAAA;CpDqlLL;AoDllLC;EAEI,6BAAA;CpDmlLL;AmDp2KD;EChQE,sBAAA;CpDumLD;AoDrmLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDumLH;AoD1mLC;EAMI,0BAAA;CpDumLL;AoD7mLC;EASI,eAAA;EACA,0BAAA;CpDumLL;AoDpmLC;EAEI,6BAAA;CpDqmLL;AmDn3KD;ECnQE,sBAAA;CpDynLD;AoDvnLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpDynLH;AoD5nLC;EAMI,0BAAA;CpDynLL;AoD/nLC;EASI,eAAA;EACA,0BAAA;CpDynLL;AoDtnLC;EAEI,6BAAA;CpDunLL;AmDl4KD;ECtQE,sBAAA;CpD2oLD;AoDzoLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD2oLH;AoD9oLC;EAMI,0BAAA;CpD2oLL;AoDjpLC;EASI,eAAA;EACA,0BAAA;CpD2oLL;AoDxoLC;EAEI,6BAAA;CpDyoLL;AmDj5KD;ECzQE,sBAAA;CpD6pLD;AoD3pLC;EACE,eAAA;EACA,0BAAA;EACA,sBAAA;CpD6pLH;AoDhqLC;EAMI,0BAAA;CpD6pLL;AoDnqLC;EASI,eAAA;EACA,0BAAA;CpD6pLL;AoD1pLC;EAEI,6BAAA;CpD2pLL;AqD3qLD;EACE,mBAAA;EACA,eAAA;EACA,UAAA;EACA,WAAA;EACA,iBAAA;CrD6qLD;AqDlrLD;;;;;EAYI,mBAAA;EACA,OAAA;EACA,QAAA;EACA,UAAA;EACA,aAAA;EACA,YAAA;EACA,UAAA;CrD6qLH;AqDxqLD;EACE,uBAAA;CrD0qLD;AqDtqLD;EACE,oBAAA;CrDwqLD;AsDnsLD;EACE,iBAAA;EACA,cAAA;EACA,oBAAA;EACA,0BAAA;EACA,0BAAA;EACA,mBAAA;EjDwDA,wDAAA;EACQ,gDAAA;CL8oLT;AsD7sLD;EASI,mBAAA;EACA,kCAAA;CtDusLH;AsDlsLD;EACE,cAAA;EACA,mBAAA;CtDosLD;AsDlsLD;EACE,aAAA;EACA,mBAAA;CtDosLD;AuD1tLD;EACE,aAAA;EACA,gBAAA;EACA,kBAAA;EACA,eAAA;EACA,eAAA;EACA,6BAAA;EjCRA,aAAA;EAGA,0BAAA;CtBmuLD;AuD3tLC;;EAEE,eAAA;EACA,sBAAA;EACA,gBAAA;EjCfF,aAAA;EAGA,0BAAA;CtB2uLD;AuDvtLC;EACE,WAAA;EACA,gBAAA;EACA,wBAAA;EACA,UAAA;EACA,yBAAA;CvDytLH;AwD9uLD;EACE,iBAAA;CxDgvLD;AwD5uLD;EACE,cAAA;EACA,iBAAA;EACA,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,kCAAA;EAIA,WAAA;CxD2uLD;AwDxuLC;EnD+GA,sCAAA;EACI,kCAAA;EACC,iCAAA;EACG,8BAAA;EAkER,oDAAA;EAEK,0CAAA;EACG,oCAAA;CL2jLT;AwD9uLC;EnD2GA,mCAAA;EACI,+BAAA;EACC,8BAAA;EACG,2BAAA;CLsoLT;AwDlvLD;EACE,mBAAA;EACA,iBAAA;CxDovLD;AwDhvLD;EACE,mBAAA;EACA,YAAA;EACA,aAAA;CxDkvLD;AwD9uLD;EACE,mBAAA;EACA,0BAAA;EACA,0BAAA;EACA,qCAAA;EACA,mBAAA;EnDaA,iDAAA;EACQ,yCAAA;EmDZR,qCAAA;UAAA,6BAAA;EAEA,WAAA;CxDgvLD;AwD5uLD;EACE,gBAAA;EACA,OAAA;EACA,SAAA;EACA,UAAA;EACA,QAAA;EACA,cAAA;EACA,0BAAA;CxD8uLD;AwD5uLC;ElCrEA,WAAA;EAGA,yBAAA;CtBkzLD;AwD/uLC;ElCtEA,aAAA;EAGA,0BAAA;CtBszLD;AwD9uLD;EACE,cAAA;EACA,iCAAA;EACA,0BAAA;CxDgvLD;AwD7uLD;EACE,iBAAA;CxD+uLD;AwD3uLD;EACE,UAAA;EACA,wBAAA;CxD6uLD;AwDxuLD;EACE,mBAAA;EACA,cAAA;CxD0uLD;AwDtuLD;EACE,cAAA;EACA,kBAAA;EACA,8BAAA;CxDwuLD;AwD3uLD;EAQI,iBAAA;EACA,iBAAA;CxDsuLH;AwD/uLD;EAaI,kBAAA;CxDquLH;AwDlvLD;EAiBI,eAAA;CxDouLH;AwD/tLD;EACE,mBAAA;EACA,aAAA;EACA,YAAA;EACA,aAAA;EACA,iBAAA;CxDiuLD;AwD/sLD;EAZE;IACE,aAAA;IACA,kBAAA;GxD8tLD;EwD5tLD;InDvEA,kDAAA;IACQ,0CAAA;GLsyLP;EwD3tLD;IAAY,aAAA;GxD8tLX;CACF;AwDztLD;EAFE;IAAY,aAAA;GxD+tLX;CACF;AyD92LD;EACE,mBAAA;EACA,cAAA;EACA,eAAA;ECRA,4DAAA;EAEA,mBAAA;EACA,oBAAA;EACA,uBAAA;EACA,iBAAA;EACA,wBAAA;EACA,iBAAA;EACA,kBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mBAAA;EACA,qBAAA;EACA,kBAAA;EDHA,gBAAA;EnCVA,WAAA;EAGA,yBAAA;CtBq4LD;AyD13LC;EnCdA,aAAA;EAGA,0BAAA;CtBy4LD;AyD73LC;EAAW,iBAAA;EAAmB,eAAA;CzDi4L/B;AyDh4LC;EAAW,iBAAA;EAAmB,eAAA;CzDo4L/B;AyDn4LC;EAAW,gBAAA;EAAmB,eAAA;CzDu4L/B;AyDt4LC;EAAW,kBAAA;EAAmB,eAAA;CzD04L/B;AyDt4LD;EACE,iBAAA;EACA,iBAAA;EACA,eAAA;EACA,mBAAA;EACA,0BAAA;EACA,mBAAA;CzDw4LD;AyDp4LD;EACE,mBAAA;EACA,SAAA;EACA,UAAA;EACA,0BAAA;EACA,oBAAA;CzDs4LD;AyDl4LC;EACE,UAAA;EACA,UAAA;EACA,kBAAA;EACA,wBAAA;EACA,0BAAA;CzDo4LH;AyDl4LC;EACE,UAAA;EACA,WAAA;EACA,oBAAA;EACA,wBAAA;EACA,0BAAA;CzDo4LH;AyDl4LC;EACE,UAAA;EACA,UAAA;EACA,oBAAA;EACA,wBAAA;EACA,0BAAA;CzDo4LH;AyDl4LC;EACE,SAAA;EACA,QAAA;EACA,iBAAA;EACA,4BAAA;EACA,4BAAA;CzDo4LH;AyDl4LC;EACE,SAAA;EACA,SAAA;EACA,iBAAA;EACA,4BAAA;EACA,2BAAA;CzDo4LH;AyDl4LC;EACE,OAAA;EACA,UAAA;EACA,kBAAA;EACA,wBAAA;EACA,6BAAA;CzDo4LH;AyDl4LC;EACE,OAAA;EACA,WAAA;EACA,iBAAA;EACA,wBAAA;EACA,6BAAA;CzDo4LH;AyDl4LC;EACE,OAAA;EACA,UAAA;EACA,iBAAA;EACA,wBAAA;EACA,6BAAA;CzDo4LH;A2Dj+LD;EACE,mBAAA;EACA,OAAA;EACA,QAAA;EACA,cAAA;EACA,cAAA;EACA,iBAAA;EACA,aAAA;EDXA,4DAAA;EAEA,mBAAA;EACA,oBAAA;EACA,uBAAA;EACA,iBAAA;EACA,wBAAA;EACA,iBAAA;EACA,kBAAA;EACA,sBAAA;EACA,kBAAA;EACA,qBAAA;EACA,oBAAA;EACA,mBAAA;EACA,qBAAA;EACA,kBAAA;ECAA,gBAAA;EAEA,0BAAA;EACA,qCAAA;UAAA,6BAAA;EACA,0BAAA;EACA,qCAAA;EACA,mBAAA;EtD8CA,kDAAA;EACQ,0CAAA;CLi8LT;A2D5+LC;EAAY,kBAAA;C3D++Lb;A2D9+LC;EAAY,kBAAA;C3Di/Lb;A2Dh/LC;EAAY,iBAAA;C3Dm/Lb;A2Dl/LC;EAAY,mBAAA;C3Dq/Lb;A2Dl/LD;EACE,UAAA;EACA,kBAAA;EACA,gBAAA;EACA,0BAAA;EACA,iCAAA;EACA,2BAAA;C3Do/LD;A2Dj/LD;EACE,kBAAA;C3Dm/LD;A2D3+LC;;EAEE,mBAAA;EACA,eAAA;EACA,SAAA;EACA,UAAA;EACA,0BAAA;EACA,oBAAA;C3D6+LH;A2D1+LD;EACE,mBAAA;C3D4+LD;A2D1+LD;EACE,mBAAA;EACA,YAAA;C3D4+LD;A2Dx+LC;EACE,UAAA;EACA,mBAAA;EACA,uBAAA;EACA,0BAAA;EACA,sCAAA;EACA,cAAA;C3D0+LH;A2Dz+LG;EACE,aAAA;EACA,YAAA;EACA,mBAAA;EACA,uBAAA;EACA,0BAAA;C3D2+LL;A2Dx+LC;EACE,SAAA;EACA,YAAA;EACA,kBAAA;EACA,qBAAA;EACA,4BAAA;EACA,wCAAA;C3D0+LH;A2Dz+LG;EACE,aAAA;EACA,UAAA;EACA,cAAA;EACA,qBAAA;EACA,4BAAA;C3D2+LL;A2Dx+LC;EACE,UAAA;EACA,mBAAA;EACA,oBAAA;EACA,6BAAA;EACA,yCAAA;EACA,WAAA;C3D0+LH;A2Dz+LG;EACE,aAAA;EACA,SAAA;EACA,mBAAA;EACA,oBAAA;EACA,6BAAA;C3D2+LL;A2Dv+LC;EACE,SAAA;EACA,aAAA;EACA,kBAAA;EACA,sBAAA;EACA,2BAAA;EACA,uCAAA;C3Dy+LH;A2Dx+LG;EACE,aAAA;EACA,WAAA;EACA,sBAAA;EACA,2BAAA;EACA,cAAA;C3D0+LL;A4DnmMD;EACE,mBAAA;C5DqmMD;A4DlmMD;EACE,mBAAA;EACA,iBAAA;EACA,YAAA;C5DomMD;A4DvmMD;EAMI,cAAA;EACA,mBAAA;EvD6KF,0CAAA;EACK,qCAAA;EACG,kCAAA;CLw7LT;A4D9mMD;;EAcM,eAAA;C5DomML;A4D1kMC;EAAA;IvDiKA,uDAAA;IAEK,6CAAA;IACG,uCAAA;IA7JR,oCAAA;IAEQ,4BAAA;IA+GR,4BAAA;IAEQ,oBAAA;GL69LP;E4DxmMG;;IvDmHJ,2CAAA;IACQ,mCAAA;IuDjHF,QAAA;G5D2mML;E4DzmMG;;IvD8GJ,4CAAA;IACQ,oCAAA;IuD5GF,QAAA;G5D4mML;E4D1mMG;;;IvDyGJ,wCAAA;IACQ,gCAAA;IuDtGF,QAAA;G5D6mML;CACF;A4DnpMD;;;EA6CI,eAAA;C5D2mMH;A4DxpMD;EAiDI,QAAA;C5D0mMH;A4D3pMD;;EAsDI,mBAAA;EACA,OAAA;EACA,YAAA;C5DymMH;A4DjqMD;EA4DI,WAAA;C5DwmMH;A4DpqMD;EA+DI,YAAA;C5DwmMH;A4DvqMD;;EAmEI,QAAA;C5DwmMH;A4D3qMD;EAuEI,YAAA;C5DumMH;A4D9qMD;EA0EI,WAAA;C5DumMH;A4D/lMD;EACE,mBAAA;EACA,OAAA;EACA,QAAA;EACA,UAAA;EACA,WAAA;EtC9FA,aAAA;EAGA,0BAAA;EsC6FA,gBAAA;EACA,eAAA;EACA,mBAAA;EACA,0CAAA;C5DkmMD;A4D7lMC;EdlGE,mGAAA;EACA,8FAAA;EACA,qHAAA;EAAA,+FAAA;EACA,4BAAA;EACA,uHAAA;C9CksMH;A4DjmMC;EACE,WAAA;EACA,SAAA;EdvGA,mGAAA;EACA,8FAAA;EACA,qHAAA;EAAA,+FAAA;EACA,4BAAA;EACA,uHAAA;C9C2sMH;A4DnmMC;;EAEE,WAAA;EACA,eAAA;EACA,sBAAA;EtCtHF,aAAA;EAGA,0BAAA;CtB0tMD;A4DpoMD;;;;EAsCI,mBAAA;EACA,SAAA;EACA,kBAAA;EACA,WAAA;EACA,sBAAA;C5DomMH;A4D9oMD;;EA8CI,UAAA;EACA,mBAAA;C5DomMH;A4DnpMD;;EAmDI,WAAA;EACA,oBAAA;C5DomMH;A4DxpMD;;EAwDI,YAAA;EACA,aAAA;EACA,eAAA;EACA,mBAAA;C5DomMH;A4D/lMG;EACE,iBAAA;C5DimML;A4D7lMG;EACE,iBAAA;C5D+lML;A4DrlMD;EACE,mBAAA;EACA,aAAA;EACA,UAAA;EACA,YAAA;EACA,WAAA;EACA,kBAAA;EACA,gBAAA;EACA,iBAAA;EACA,mBAAA;C5DulMD;A4DhmMD;EAYI,sBAAA;EACA,YAAA;EACA,aAAA;EACA,YAAA;EACA,oBAAA;EACA,0BAAA;EACA,oBAAA;EACA,gBAAA;EAWA,0BAAA;EACA,mCAAA;C5D6kMH;A4D5mMD;EAkCI,UAAA;EACA,YAAA;EACA,aAAA;EACA,0BAAA;C5D6kMH;A4DtkMD;EACE,mBAAA;EACA,UAAA;EACA,WAAA;EACA,aAAA;EACA,YAAA;EACA,kBAAA;EACA,qBAAA;EACA,eAAA;EACA,mBAAA;EACA,0CAAA;C5DwkMD;A4DvkMC;EACE,kBAAA;C5DykMH;A4DhiMD;EAhCE;;;;IAKI,YAAA;IACA,aAAA;IACA,kBAAA;IACA,gBAAA;G5DkkMH;E4D1kMD;;IAYI,mBAAA;G5DkkMH;E4D9kMD;;IAgBI,oBAAA;G5DkkMH;E4D7jMD;IACE,UAAA;IACA,WAAA;IACA,qBAAA;G5D+jMD;E4D3jMD;IACE,aAAA;G5D6jMD;CACF;A6D3zMC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAEE,aAAA;EACA,eAAA;C7Dy1MH;A6Dv1MC;;;;;;;;;;;;;;;EACE,YAAA;C7Du2MH;AiC/2MD;E6BRE,eAAA;EACA,kBAAA;EACA,mBAAA;C9D03MD;AiCj3MD;EACE,wBAAA;CjCm3MD;AiCj3MD;EACE,uBAAA;CjCm3MD;AiC32MD;EACE,yBAAA;CjC62MD;AiC32MD;EACE,0BAAA;CjC62MD;AiC32MD;EACE,mBAAA;CjC62MD;AiC32MD;E8BzBE,YAAA;EACA,mBAAA;EACA,kBAAA;EACA,8BAAA;EACA,UAAA;C/Du4MD;AiCz2MD;EACE,yBAAA;CjC22MD;AiCp2MD;EACE,gBAAA;CjCs2MD;AgEv4MD;EACE,oBAAA;ChEy4MD;AgEn4MD;;;;ECdE,yBAAA;CjEu5MD;AgEl4MD;;;;;;;;;;;;EAYE,yBAAA;ChEo4MD;AgE73MD;EAAA;IChDE,0BAAA;GjEi7MC;EiEh7MD;IAAU,0BAAA;GjEm7MT;EiEl7MD;IAAU,8BAAA;GjEq7MT;EiEp7MD;;IACU,+BAAA;GjEu7MT;CACF;AgEv4MD;EAAA;IAFI,0BAAA;GhE64MD;CACF;AgEv4MD;EAAA;IAFI,2BAAA;GhE64MD;CACF;AgEv4MD;EAAA;IAFI,iCAAA;GhE64MD;CACF;AgEt4MD;EAAA;ICrEE,0BAAA;GjE+8MC;EiE98MD;IAAU,0BAAA;GjEi9MT;EiEh9MD;IAAU,8BAAA;GjEm9MT;EiEl9MD;;IACU,+BAAA;GjEq9MT;CACF;AgEh5MD;EAAA;IAFI,0BAAA;GhEs5MD;CACF;AgEh5MD;EAAA;IAFI,2BAAA;GhEs5MD;CACF;AgEh5MD;EAAA;IAFI,iCAAA;GhEs5MD;CACF;AgE/4MD;EAAA;IC1FE,0BAAA;GjE6+MC;EiE5+MD;IAAU,0BAAA;GjE++MT;EiE9+MD;IAAU,8BAAA;GjEi/MT;EiEh/MD;;IACU,+BAAA;GjEm/MT;CACF;AgEz5MD;EAAA;IAFI,0BAAA;GhE+5MD;CACF;AgEz5MD;EAAA;IAFI,2BAAA;GhE+5MD;CACF;AgEz5MD;EAAA;IAFI,iCAAA;GhE+5MD;CACF;AgEx5MD;EAAA;IC/GE,0BAAA;GjE2gNC;EiE1gND;IAAU,0BAAA;GjE6gNT;EiE5gND;IAAU,8BAAA;GjE+gNT;EiE9gND;;IACU,+BAAA;GjEihNT;CACF;AgEl6MD;EAAA;IAFI,0BAAA;GhEw6MD;CACF;AgEl6MD;EAAA;IAFI,2BAAA;GhEw6MD;CACF;AgEl6MD;EAAA;IAFI,iCAAA;GhEw6MD;CACF;AgEj6MD;EAAA;IC5HE,yBAAA;GjEiiNC;CACF;AgEj6MD;EAAA;ICjIE,yBAAA;GjEsiNC;CACF;AgEj6MD;EAAA;ICtIE,yBAAA;GjE2iNC;CACF;AgEj6MD;EAAA;IC3IE,yBAAA;GjEgjNC;CACF;AgE95MD;ECnJE,yBAAA;CjEojND;AgE35MD;EAAA;ICjKE,0BAAA;GjEgkNC;EiE/jND;IAAU,0BAAA;GjEkkNT;EiEjkND;IAAU,8BAAA;GjEokNT;EiEnkND;;IACU,+BAAA;GjEskNT;CACF;AgEz6MD;EACE,yBAAA;ChE26MD;AgEt6MD;EAAA;IAFI,0BAAA;GhE46MD;CACF;AgE16MD;EACE,yBAAA;ChE46MD;AgEv6MD;EAAA;IAFI,2BAAA;GhE66MD;CACF;AgE36MD;EACE,yBAAA;ChE66MD;AgEx6MD;EAAA;IAFI,iCAAA;GhE86MD;CACF;AgEv6MD;EAAA;ICpLE,yBAAA;GjE+lNC;CACF","file":"bootstrap.css","sourcesContent":["/*!\n * Bootstrap v3.3.5 (http://getbootstrap.com)\n * Copyright 2011-2015 Twitter, Inc.\n * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)\n */\n/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\nhtml {\n font-family: sans-serif;\n -ms-text-size-adjust: 100%;\n -webkit-text-size-adjust: 100%;\n}\nbody {\n margin: 0;\n}\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block;\n vertical-align: baseline;\n}\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n[hidden],\ntemplate {\n display: none;\n}\na {\n background-color: transparent;\n}\na:active,\na:hover {\n outline: 0;\n}\nabbr[title] {\n border-bottom: 1px dotted;\n}\nb,\nstrong {\n font-weight: bold;\n}\ndfn {\n font-style: italic;\n}\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\nmark {\n background: #ff0;\n color: #000;\n}\nsmall {\n font-size: 80%;\n}\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\nsup {\n top: -0.5em;\n}\nsub {\n bottom: -0.25em;\n}\nimg {\n border: 0;\n}\nsvg:not(:root) {\n overflow: hidden;\n}\nfigure {\n margin: 1em 40px;\n}\nhr {\n box-sizing: content-box;\n height: 0;\n}\npre {\n overflow: auto;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit;\n font: inherit;\n margin: 0;\n}\nbutton {\n overflow: visible;\n}\nbutton,\nselect {\n text-transform: none;\n}\nbutton,\nhtml input[type=\"button\"],\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button;\n cursor: pointer;\n}\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\ninput {\n line-height: normal;\n}\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box;\n padding: 0;\n}\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: textfield;\n box-sizing: content-box;\n}\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\nlegend {\n border: 0;\n padding: 0;\n}\ntextarea {\n overflow: auto;\n}\noptgroup {\n font-weight: bold;\n}\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\ntd,\nth {\n padding: 0;\n}\n/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important;\n box-shadow: none !important;\n text-shadow: none !important;\n }\n a,\n a:visited {\n text-decoration: underline;\n }\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n thead {\n display: table-header-group;\n }\n tr,\n img {\n page-break-inside: avoid;\n }\n img {\n max-width: 100% !important;\n }\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n h2,\n h3 {\n page-break-after: avoid;\n }\n .navbar {\n display: none;\n }\n .btn > .caret,\n .dropup > .btn > .caret {\n border-top-color: #000 !important;\n }\n .label {\n border: 1px solid #000;\n }\n .table {\n border-collapse: collapse !important;\n }\n .table td,\n .table th {\n background-color: #fff !important;\n }\n .table-bordered th,\n .table-bordered td {\n border: 1px solid #ddd !important;\n }\n}\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('../fonts/glyphicons-halflings-regular.eot');\n src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');\n}\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n.glyphicon-asterisk:before {\n content: \"\\2a\";\n}\n.glyphicon-plus:before {\n content: \"\\2b\";\n}\n.glyphicon-euro:before,\n.glyphicon-eur:before {\n content: \"\\20ac\";\n}\n.glyphicon-minus:before {\n content: \"\\2212\";\n}\n.glyphicon-cloud:before {\n content: \"\\2601\";\n}\n.glyphicon-envelope:before {\n content: \"\\2709\";\n}\n.glyphicon-pencil:before {\n content: \"\\270f\";\n}\n.glyphicon-glass:before {\n content: \"\\e001\";\n}\n.glyphicon-music:before {\n content: \"\\e002\";\n}\n.glyphicon-search:before {\n content: \"\\e003\";\n}\n.glyphicon-heart:before {\n content: \"\\e005\";\n}\n.glyphicon-star:before {\n content: \"\\e006\";\n}\n.glyphicon-star-empty:before {\n content: \"\\e007\";\n}\n.glyphicon-user:before {\n content: \"\\e008\";\n}\n.glyphicon-film:before {\n content: \"\\e009\";\n}\n.glyphicon-th-large:before {\n content: \"\\e010\";\n}\n.glyphicon-th:before {\n content: \"\\e011\";\n}\n.glyphicon-th-list:before {\n content: \"\\e012\";\n}\n.glyphicon-ok:before {\n content: \"\\e013\";\n}\n.glyphicon-remove:before {\n content: \"\\e014\";\n}\n.glyphicon-zoom-in:before {\n content: \"\\e015\";\n}\n.glyphicon-zoom-out:before {\n content: \"\\e016\";\n}\n.glyphicon-off:before {\n content: \"\\e017\";\n}\n.glyphicon-signal:before {\n content: \"\\e018\";\n}\n.glyphicon-cog:before {\n content: \"\\e019\";\n}\n.glyphicon-trash:before {\n content: \"\\e020\";\n}\n.glyphicon-home:before {\n content: \"\\e021\";\n}\n.glyphicon-file:before {\n content: \"\\e022\";\n}\n.glyphicon-time:before {\n content: \"\\e023\";\n}\n.glyphicon-road:before {\n content: \"\\e024\";\n}\n.glyphicon-download-alt:before {\n content: \"\\e025\";\n}\n.glyphicon-download:before {\n content: \"\\e026\";\n}\n.glyphicon-upload:before {\n content: \"\\e027\";\n}\n.glyphicon-inbox:before {\n content: \"\\e028\";\n}\n.glyphicon-play-circle:before {\n content: \"\\e029\";\n}\n.glyphicon-repeat:before {\n content: \"\\e030\";\n}\n.glyphicon-refresh:before {\n content: \"\\e031\";\n}\n.glyphicon-list-alt:before {\n content: \"\\e032\";\n}\n.glyphicon-lock:before {\n content: \"\\e033\";\n}\n.glyphicon-flag:before {\n content: \"\\e034\";\n}\n.glyphicon-headphones:before {\n content: \"\\e035\";\n}\n.glyphicon-volume-off:before {\n content: \"\\e036\";\n}\n.glyphicon-volume-down:before {\n content: \"\\e037\";\n}\n.glyphicon-volume-up:before {\n content: \"\\e038\";\n}\n.glyphicon-qrcode:before {\n content: \"\\e039\";\n}\n.glyphicon-barcode:before {\n content: \"\\e040\";\n}\n.glyphicon-tag:before {\n content: \"\\e041\";\n}\n.glyphicon-tags:before {\n content: \"\\e042\";\n}\n.glyphicon-book:before {\n content: \"\\e043\";\n}\n.glyphicon-bookmark:before {\n content: \"\\e044\";\n}\n.glyphicon-print:before {\n content: \"\\e045\";\n}\n.glyphicon-camera:before {\n content: \"\\e046\";\n}\n.glyphicon-font:before {\n content: \"\\e047\";\n}\n.glyphicon-bold:before {\n content: \"\\e048\";\n}\n.glyphicon-italic:before {\n content: \"\\e049\";\n}\n.glyphicon-text-height:before {\n content: \"\\e050\";\n}\n.glyphicon-text-width:before {\n content: \"\\e051\";\n}\n.glyphicon-align-left:before {\n content: \"\\e052\";\n}\n.glyphicon-align-center:before {\n content: \"\\e053\";\n}\n.glyphicon-align-right:before {\n content: \"\\e054\";\n}\n.glyphicon-align-justify:before {\n content: \"\\e055\";\n}\n.glyphicon-list:before {\n content: \"\\e056\";\n}\n.glyphicon-indent-left:before {\n content: \"\\e057\";\n}\n.glyphicon-indent-right:before {\n content: \"\\e058\";\n}\n.glyphicon-facetime-video:before {\n content: \"\\e059\";\n}\n.glyphicon-picture:before {\n content: \"\\e060\";\n}\n.glyphicon-map-marker:before {\n content: \"\\e062\";\n}\n.glyphicon-adjust:before {\n content: \"\\e063\";\n}\n.glyphicon-tint:before {\n content: \"\\e064\";\n}\n.glyphicon-edit:before {\n content: \"\\e065\";\n}\n.glyphicon-share:before {\n content: \"\\e066\";\n}\n.glyphicon-check:before {\n content: \"\\e067\";\n}\n.glyphicon-move:before {\n content: \"\\e068\";\n}\n.glyphicon-step-backward:before {\n content: \"\\e069\";\n}\n.glyphicon-fast-backward:before {\n content: \"\\e070\";\n}\n.glyphicon-backward:before {\n content: \"\\e071\";\n}\n.glyphicon-play:before {\n content: \"\\e072\";\n}\n.glyphicon-pause:before {\n content: \"\\e073\";\n}\n.glyphicon-stop:before {\n content: \"\\e074\";\n}\n.glyphicon-forward:before {\n content: \"\\e075\";\n}\n.glyphicon-fast-forward:before {\n content: \"\\e076\";\n}\n.glyphicon-step-forward:before {\n content: \"\\e077\";\n}\n.glyphicon-eject:before {\n content: \"\\e078\";\n}\n.glyphicon-chevron-left:before {\n content: \"\\e079\";\n}\n.glyphicon-chevron-right:before {\n content: \"\\e080\";\n}\n.glyphicon-plus-sign:before {\n content: \"\\e081\";\n}\n.glyphicon-minus-sign:before {\n content: \"\\e082\";\n}\n.glyphicon-remove-sign:before {\n content: \"\\e083\";\n}\n.glyphicon-ok-sign:before {\n content: \"\\e084\";\n}\n.glyphicon-question-sign:before {\n content: \"\\e085\";\n}\n.glyphicon-info-sign:before {\n content: \"\\e086\";\n}\n.glyphicon-screenshot:before {\n content: \"\\e087\";\n}\n.glyphicon-remove-circle:before {\n content: \"\\e088\";\n}\n.glyphicon-ok-circle:before {\n content: \"\\e089\";\n}\n.glyphicon-ban-circle:before {\n content: \"\\e090\";\n}\n.glyphicon-arrow-left:before {\n content: \"\\e091\";\n}\n.glyphicon-arrow-right:before {\n content: \"\\e092\";\n}\n.glyphicon-arrow-up:before {\n content: \"\\e093\";\n}\n.glyphicon-arrow-down:before {\n content: \"\\e094\";\n}\n.glyphicon-share-alt:before {\n content: \"\\e095\";\n}\n.glyphicon-resize-full:before {\n content: \"\\e096\";\n}\n.glyphicon-resize-small:before {\n content: \"\\e097\";\n}\n.glyphicon-exclamation-sign:before {\n content: \"\\e101\";\n}\n.glyphicon-gift:before {\n content: \"\\e102\";\n}\n.glyphicon-leaf:before {\n content: \"\\e103\";\n}\n.glyphicon-fire:before {\n content: \"\\e104\";\n}\n.glyphicon-eye-open:before {\n content: \"\\e105\";\n}\n.glyphicon-eye-close:before {\n content: \"\\e106\";\n}\n.glyphicon-warning-sign:before {\n content: \"\\e107\";\n}\n.glyphicon-plane:before {\n content: \"\\e108\";\n}\n.glyphicon-calendar:before {\n content: \"\\e109\";\n}\n.glyphicon-random:before {\n content: \"\\e110\";\n}\n.glyphicon-comment:before {\n content: \"\\e111\";\n}\n.glyphicon-magnet:before {\n content: \"\\e112\";\n}\n.glyphicon-chevron-up:before {\n content: \"\\e113\";\n}\n.glyphicon-chevron-down:before {\n content: \"\\e114\";\n}\n.glyphicon-retweet:before {\n content: \"\\e115\";\n}\n.glyphicon-shopping-cart:before {\n content: \"\\e116\";\n}\n.glyphicon-folder-close:before {\n content: \"\\e117\";\n}\n.glyphicon-folder-open:before {\n content: \"\\e118\";\n}\n.glyphicon-resize-vertical:before {\n content: \"\\e119\";\n}\n.glyphicon-resize-horizontal:before {\n content: \"\\e120\";\n}\n.glyphicon-hdd:before {\n content: \"\\e121\";\n}\n.glyphicon-bullhorn:before {\n content: \"\\e122\";\n}\n.glyphicon-bell:before {\n content: \"\\e123\";\n}\n.glyphicon-certificate:before {\n content: \"\\e124\";\n}\n.glyphicon-thumbs-up:before {\n content: \"\\e125\";\n}\n.glyphicon-thumbs-down:before {\n content: \"\\e126\";\n}\n.glyphicon-hand-right:before {\n content: \"\\e127\";\n}\n.glyphicon-hand-left:before {\n content: \"\\e128\";\n}\n.glyphicon-hand-up:before {\n content: \"\\e129\";\n}\n.glyphicon-hand-down:before {\n content: \"\\e130\";\n}\n.glyphicon-circle-arrow-right:before {\n content: \"\\e131\";\n}\n.glyphicon-circle-arrow-left:before {\n content: \"\\e132\";\n}\n.glyphicon-circle-arrow-up:before {\n content: \"\\e133\";\n}\n.glyphicon-circle-arrow-down:before {\n content: \"\\e134\";\n}\n.glyphicon-globe:before {\n content: \"\\e135\";\n}\n.glyphicon-wrench:before {\n content: \"\\e136\";\n}\n.glyphicon-tasks:before {\n content: \"\\e137\";\n}\n.glyphicon-filter:before {\n content: \"\\e138\";\n}\n.glyphicon-briefcase:before {\n content: \"\\e139\";\n}\n.glyphicon-fullscreen:before {\n content: \"\\e140\";\n}\n.glyphicon-dashboard:before {\n content: \"\\e141\";\n}\n.glyphicon-paperclip:before {\n content: \"\\e142\";\n}\n.glyphicon-heart-empty:before {\n content: \"\\e143\";\n}\n.glyphicon-link:before {\n content: \"\\e144\";\n}\n.glyphicon-phone:before {\n content: \"\\e145\";\n}\n.glyphicon-pushpin:before {\n content: \"\\e146\";\n}\n.glyphicon-usd:before {\n content: \"\\e148\";\n}\n.glyphicon-gbp:before {\n content: \"\\e149\";\n}\n.glyphicon-sort:before {\n content: \"\\e150\";\n}\n.glyphicon-sort-by-alphabet:before {\n content: \"\\e151\";\n}\n.glyphicon-sort-by-alphabet-alt:before {\n content: \"\\e152\";\n}\n.glyphicon-sort-by-order:before {\n content: \"\\e153\";\n}\n.glyphicon-sort-by-order-alt:before {\n content: \"\\e154\";\n}\n.glyphicon-sort-by-attributes:before {\n content: \"\\e155\";\n}\n.glyphicon-sort-by-attributes-alt:before {\n content: \"\\e156\";\n}\n.glyphicon-unchecked:before {\n content: \"\\e157\";\n}\n.glyphicon-expand:before {\n content: \"\\e158\";\n}\n.glyphicon-collapse-down:before {\n content: \"\\e159\";\n}\n.glyphicon-collapse-up:before {\n content: \"\\e160\";\n}\n.glyphicon-log-in:before {\n content: \"\\e161\";\n}\n.glyphicon-flash:before {\n content: \"\\e162\";\n}\n.glyphicon-log-out:before {\n content: \"\\e163\";\n}\n.glyphicon-new-window:before {\n content: \"\\e164\";\n}\n.glyphicon-record:before {\n content: \"\\e165\";\n}\n.glyphicon-save:before {\n content: \"\\e166\";\n}\n.glyphicon-open:before {\n content: \"\\e167\";\n}\n.glyphicon-saved:before {\n content: \"\\e168\";\n}\n.glyphicon-import:before {\n content: \"\\e169\";\n}\n.glyphicon-export:before {\n content: \"\\e170\";\n}\n.glyphicon-send:before {\n content: \"\\e171\";\n}\n.glyphicon-floppy-disk:before {\n content: \"\\e172\";\n}\n.glyphicon-floppy-saved:before {\n content: \"\\e173\";\n}\n.glyphicon-floppy-remove:before {\n content: \"\\e174\";\n}\n.glyphicon-floppy-save:before {\n content: \"\\e175\";\n}\n.glyphicon-floppy-open:before {\n content: \"\\e176\";\n}\n.glyphicon-credit-card:before {\n content: \"\\e177\";\n}\n.glyphicon-transfer:before {\n content: \"\\e178\";\n}\n.glyphicon-cutlery:before {\n content: \"\\e179\";\n}\n.glyphicon-header:before {\n content: \"\\e180\";\n}\n.glyphicon-compressed:before {\n content: \"\\e181\";\n}\n.glyphicon-earphone:before {\n content: \"\\e182\";\n}\n.glyphicon-phone-alt:before {\n content: \"\\e183\";\n}\n.glyphicon-tower:before {\n content: \"\\e184\";\n}\n.glyphicon-stats:before {\n content: \"\\e185\";\n}\n.glyphicon-sd-video:before {\n content: \"\\e186\";\n}\n.glyphicon-hd-video:before {\n content: \"\\e187\";\n}\n.glyphicon-subtitles:before {\n content: \"\\e188\";\n}\n.glyphicon-sound-stereo:before {\n content: \"\\e189\";\n}\n.glyphicon-sound-dolby:before {\n content: \"\\e190\";\n}\n.glyphicon-sound-5-1:before {\n content: \"\\e191\";\n}\n.glyphicon-sound-6-1:before {\n content: \"\\e192\";\n}\n.glyphicon-sound-7-1:before {\n content: \"\\e193\";\n}\n.glyphicon-copyright-mark:before {\n content: \"\\e194\";\n}\n.glyphicon-registration-mark:before {\n content: \"\\e195\";\n}\n.glyphicon-cloud-download:before {\n content: \"\\e197\";\n}\n.glyphicon-cloud-upload:before {\n content: \"\\e198\";\n}\n.glyphicon-tree-conifer:before {\n content: \"\\e199\";\n}\n.glyphicon-tree-deciduous:before {\n content: \"\\e200\";\n}\n.glyphicon-cd:before {\n content: \"\\e201\";\n}\n.glyphicon-save-file:before {\n content: \"\\e202\";\n}\n.glyphicon-open-file:before {\n content: \"\\e203\";\n}\n.glyphicon-level-up:before {\n content: \"\\e204\";\n}\n.glyphicon-copy:before {\n content: \"\\e205\";\n}\n.glyphicon-paste:before {\n content: \"\\e206\";\n}\n.glyphicon-alert:before {\n content: \"\\e209\";\n}\n.glyphicon-equalizer:before {\n content: \"\\e210\";\n}\n.glyphicon-king:before {\n content: \"\\e211\";\n}\n.glyphicon-queen:before {\n content: \"\\e212\";\n}\n.glyphicon-pawn:before {\n content: \"\\e213\";\n}\n.glyphicon-bishop:before {\n content: \"\\e214\";\n}\n.glyphicon-knight:before {\n content: \"\\e215\";\n}\n.glyphicon-baby-formula:before {\n content: \"\\e216\";\n}\n.glyphicon-tent:before {\n content: \"\\26fa\";\n}\n.glyphicon-blackboard:before {\n content: \"\\e218\";\n}\n.glyphicon-bed:before {\n content: \"\\e219\";\n}\n.glyphicon-apple:before {\n content: \"\\f8ff\";\n}\n.glyphicon-erase:before {\n content: \"\\e221\";\n}\n.glyphicon-hourglass:before {\n content: \"\\231b\";\n}\n.glyphicon-lamp:before {\n content: \"\\e223\";\n}\n.glyphicon-duplicate:before {\n content: \"\\e224\";\n}\n.glyphicon-piggy-bank:before {\n content: \"\\e225\";\n}\n.glyphicon-scissors:before {\n content: \"\\e226\";\n}\n.glyphicon-bitcoin:before {\n content: \"\\e227\";\n}\n.glyphicon-btc:before {\n content: \"\\e227\";\n}\n.glyphicon-xbt:before {\n content: \"\\e227\";\n}\n.glyphicon-yen:before {\n content: \"\\00a5\";\n}\n.glyphicon-jpy:before {\n content: \"\\00a5\";\n}\n.glyphicon-ruble:before {\n content: \"\\20bd\";\n}\n.glyphicon-rub:before {\n content: \"\\20bd\";\n}\n.glyphicon-scale:before {\n content: \"\\e230\";\n}\n.glyphicon-ice-lolly:before {\n content: \"\\e231\";\n}\n.glyphicon-ice-lolly-tasted:before {\n content: \"\\e232\";\n}\n.glyphicon-education:before {\n content: \"\\e233\";\n}\n.glyphicon-option-horizontal:before {\n content: \"\\e234\";\n}\n.glyphicon-option-vertical:before {\n content: \"\\e235\";\n}\n.glyphicon-menu-hamburger:before {\n content: \"\\e236\";\n}\n.glyphicon-modal-window:before {\n content: \"\\e237\";\n}\n.glyphicon-oil:before {\n content: \"\\e238\";\n}\n.glyphicon-grain:before {\n content: \"\\e239\";\n}\n.glyphicon-sunglasses:before {\n content: \"\\e240\";\n}\n.glyphicon-text-size:before {\n content: \"\\e241\";\n}\n.glyphicon-text-color:before {\n content: \"\\e242\";\n}\n.glyphicon-text-background:before {\n content: \"\\e243\";\n}\n.glyphicon-object-align-top:before {\n content: \"\\e244\";\n}\n.glyphicon-object-align-bottom:before {\n content: \"\\e245\";\n}\n.glyphicon-object-align-horizontal:before {\n content: \"\\e246\";\n}\n.glyphicon-object-align-left:before {\n content: \"\\e247\";\n}\n.glyphicon-object-align-vertical:before {\n content: \"\\e248\";\n}\n.glyphicon-object-align-right:before {\n content: \"\\e249\";\n}\n.glyphicon-triangle-right:before {\n content: \"\\e250\";\n}\n.glyphicon-triangle-left:before {\n content: \"\\e251\";\n}\n.glyphicon-triangle-bottom:before {\n content: \"\\e252\";\n}\n.glyphicon-triangle-top:before {\n content: \"\\e253\";\n}\n.glyphicon-console:before {\n content: \"\\e254\";\n}\n.glyphicon-superscript:before {\n content: \"\\e255\";\n}\n.glyphicon-subscript:before {\n content: \"\\e256\";\n}\n.glyphicon-menu-left:before {\n content: \"\\e257\";\n}\n.glyphicon-menu-right:before {\n content: \"\\e258\";\n}\n.glyphicon-menu-down:before {\n content: \"\\e259\";\n}\n.glyphicon-menu-up:before {\n content: \"\\e260\";\n}\n* {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\n*:before,\n*:after {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n}\nbody {\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-size: 14px;\n line-height: 1.42857143;\n color: #333333;\n background-color: #ffffff;\n}\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\na {\n color: #337ab7;\n text-decoration: none;\n}\na:hover,\na:focus {\n color: #23527c;\n text-decoration: underline;\n}\na:focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\nfigure {\n margin: 0;\n}\nimg {\n vertical-align: middle;\n}\n.img-responsive,\n.thumbnail > img,\n.thumbnail a > img,\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n display: block;\n max-width: 100%;\n height: auto;\n}\n.img-rounded {\n border-radius: 6px;\n}\n.img-thumbnail {\n padding: 4px;\n line-height: 1.42857143;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 4px;\n -webkit-transition: all 0.2s ease-in-out;\n -o-transition: all 0.2s ease-in-out;\n transition: all 0.2s ease-in-out;\n display: inline-block;\n max-width: 100%;\n height: auto;\n}\n.img-circle {\n border-radius: 50%;\n}\nhr {\n margin-top: 20px;\n margin-bottom: 20px;\n border: 0;\n border-top: 1px solid #eeeeee;\n}\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n border: 0;\n}\n.sr-only-focusable:active,\n.sr-only-focusable:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n}\n[role=\"button\"] {\n cursor: pointer;\n}\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\n.h1,\n.h2,\n.h3,\n.h4,\n.h5,\n.h6 {\n font-family: inherit;\n font-weight: 500;\n line-height: 1.1;\n color: inherit;\n}\nh1 small,\nh2 small,\nh3 small,\nh4 small,\nh5 small,\nh6 small,\n.h1 small,\n.h2 small,\n.h3 small,\n.h4 small,\n.h5 small,\n.h6 small,\nh1 .small,\nh2 .small,\nh3 .small,\nh4 .small,\nh5 .small,\nh6 .small,\n.h1 .small,\n.h2 .small,\n.h3 .small,\n.h4 .small,\n.h5 .small,\n.h6 .small {\n font-weight: normal;\n line-height: 1;\n color: #777777;\n}\nh1,\n.h1,\nh2,\n.h2,\nh3,\n.h3 {\n margin-top: 20px;\n margin-bottom: 10px;\n}\nh1 small,\n.h1 small,\nh2 small,\n.h2 small,\nh3 small,\n.h3 small,\nh1 .small,\n.h1 .small,\nh2 .small,\n.h2 .small,\nh3 .small,\n.h3 .small {\n font-size: 65%;\n}\nh4,\n.h4,\nh5,\n.h5,\nh6,\n.h6 {\n margin-top: 10px;\n margin-bottom: 10px;\n}\nh4 small,\n.h4 small,\nh5 small,\n.h5 small,\nh6 small,\n.h6 small,\nh4 .small,\n.h4 .small,\nh5 .small,\n.h5 .small,\nh6 .small,\n.h6 .small {\n font-size: 75%;\n}\nh1,\n.h1 {\n font-size: 36px;\n}\nh2,\n.h2 {\n font-size: 30px;\n}\nh3,\n.h3 {\n font-size: 24px;\n}\nh4,\n.h4 {\n font-size: 18px;\n}\nh5,\n.h5 {\n font-size: 14px;\n}\nh6,\n.h6 {\n font-size: 12px;\n}\np {\n margin: 0 0 10px;\n}\n.lead {\n margin-bottom: 20px;\n font-size: 16px;\n font-weight: 300;\n line-height: 1.4;\n}\n@media (min-width: 768px) {\n .lead {\n font-size: 21px;\n }\n}\nsmall,\n.small {\n font-size: 85%;\n}\nmark,\n.mark {\n background-color: #fcf8e3;\n padding: .2em;\n}\n.text-left {\n text-align: left;\n}\n.text-right {\n text-align: right;\n}\n.text-center {\n text-align: center;\n}\n.text-justify {\n text-align: justify;\n}\n.text-nowrap {\n white-space: nowrap;\n}\n.text-lowercase {\n text-transform: lowercase;\n}\n.text-uppercase {\n text-transform: uppercase;\n}\n.text-capitalize {\n text-transform: capitalize;\n}\n.text-muted {\n color: #777777;\n}\n.text-primary {\n color: #337ab7;\n}\na.text-primary:hover,\na.text-primary:focus {\n color: #286090;\n}\n.text-success {\n color: #3c763d;\n}\na.text-success:hover,\na.text-success:focus {\n color: #2b542c;\n}\n.text-info {\n color: #31708f;\n}\na.text-info:hover,\na.text-info:focus {\n color: #245269;\n}\n.text-warning {\n color: #8a6d3b;\n}\na.text-warning:hover,\na.text-warning:focus {\n color: #66512c;\n}\n.text-danger {\n color: #a94442;\n}\na.text-danger:hover,\na.text-danger:focus {\n color: #843534;\n}\n.bg-primary {\n color: #fff;\n background-color: #337ab7;\n}\na.bg-primary:hover,\na.bg-primary:focus {\n background-color: #286090;\n}\n.bg-success {\n background-color: #dff0d8;\n}\na.bg-success:hover,\na.bg-success:focus {\n background-color: #c1e2b3;\n}\n.bg-info {\n background-color: #d9edf7;\n}\na.bg-info:hover,\na.bg-info:focus {\n background-color: #afd9ee;\n}\n.bg-warning {\n background-color: #fcf8e3;\n}\na.bg-warning:hover,\na.bg-warning:focus {\n background-color: #f7ecb5;\n}\n.bg-danger {\n background-color: #f2dede;\n}\na.bg-danger:hover,\na.bg-danger:focus {\n background-color: #e4b9b9;\n}\n.page-header {\n padding-bottom: 9px;\n margin: 40px 0 20px;\n border-bottom: 1px solid #eeeeee;\n}\nul,\nol {\n margin-top: 0;\n margin-bottom: 10px;\n}\nul ul,\nol ul,\nul ol,\nol ol {\n margin-bottom: 0;\n}\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n.list-inline {\n padding-left: 0;\n list-style: none;\n margin-left: -5px;\n}\n.list-inline > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n}\ndl {\n margin-top: 0;\n margin-bottom: 20px;\n}\ndt,\ndd {\n line-height: 1.42857143;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0;\n}\n@media (min-width: 768px) {\n .dl-horizontal dt {\n float: left;\n width: 160px;\n clear: left;\n text-align: right;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .dl-horizontal dd {\n margin-left: 180px;\n }\n}\nabbr[title],\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted #777777;\n}\n.initialism {\n font-size: 90%;\n text-transform: uppercase;\n}\nblockquote {\n padding: 10px 20px;\n margin: 0 0 20px;\n font-size: 17.5px;\n border-left: 5px solid #eeeeee;\n}\nblockquote p:last-child,\nblockquote ul:last-child,\nblockquote ol:last-child {\n margin-bottom: 0;\n}\nblockquote footer,\nblockquote small,\nblockquote .small {\n display: block;\n font-size: 80%;\n line-height: 1.42857143;\n color: #777777;\n}\nblockquote footer:before,\nblockquote small:before,\nblockquote .small:before {\n content: '\\2014 \\00A0';\n}\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid #eeeeee;\n border-left: 0;\n text-align: right;\n}\n.blockquote-reverse footer:before,\nblockquote.pull-right footer:before,\n.blockquote-reverse small:before,\nblockquote.pull-right small:before,\n.blockquote-reverse .small:before,\nblockquote.pull-right .small:before {\n content: '';\n}\n.blockquote-reverse footer:after,\nblockquote.pull-right footer:after,\n.blockquote-reverse small:after,\nblockquote.pull-right small:after,\n.blockquote-reverse .small:after,\nblockquote.pull-right .small:after {\n content: '\\00A0 \\2014';\n}\naddress {\n margin-bottom: 20px;\n font-style: normal;\n line-height: 1.42857143;\n}\ncode,\nkbd,\npre,\nsamp {\n font-family: Menlo, Monaco, Consolas, \"Courier New\", monospace;\n}\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: #c7254e;\n background-color: #f9f2f4;\n border-radius: 4px;\n}\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: #ffffff;\n background-color: #333333;\n border-radius: 3px;\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\nkbd kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n}\npre {\n display: block;\n padding: 9.5px;\n margin: 0 0 10px;\n font-size: 13px;\n line-height: 1.42857143;\n word-break: break-all;\n word-wrap: break-word;\n color: #333333;\n background-color: #f5f5f5;\n border: 1px solid #cccccc;\n border-radius: 4px;\n}\npre code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n}\n.pre-scrollable {\n max-height: 340px;\n overflow-y: scroll;\n}\n.container {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n@media (min-width: 768px) {\n .container {\n width: 750px;\n }\n}\n@media (min-width: 992px) {\n .container {\n width: 970px;\n }\n}\n@media (min-width: 1200px) {\n .container {\n width: 1170px;\n }\n}\n.container-fluid {\n margin-right: auto;\n margin-left: auto;\n padding-left: 15px;\n padding-right: 15px;\n}\n.row {\n margin-left: -15px;\n margin-right: -15px;\n}\n.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {\n position: relative;\n min-height: 1px;\n padding-left: 15px;\n padding-right: 15px;\n}\n.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {\n float: left;\n}\n.col-xs-12 {\n width: 100%;\n}\n.col-xs-11 {\n width: 91.66666667%;\n}\n.col-xs-10 {\n width: 83.33333333%;\n}\n.col-xs-9 {\n width: 75%;\n}\n.col-xs-8 {\n width: 66.66666667%;\n}\n.col-xs-7 {\n width: 58.33333333%;\n}\n.col-xs-6 {\n width: 50%;\n}\n.col-xs-5 {\n width: 41.66666667%;\n}\n.col-xs-4 {\n width: 33.33333333%;\n}\n.col-xs-3 {\n width: 25%;\n}\n.col-xs-2 {\n width: 16.66666667%;\n}\n.col-xs-1 {\n width: 8.33333333%;\n}\n.col-xs-pull-12 {\n right: 100%;\n}\n.col-xs-pull-11 {\n right: 91.66666667%;\n}\n.col-xs-pull-10 {\n right: 83.33333333%;\n}\n.col-xs-pull-9 {\n right: 75%;\n}\n.col-xs-pull-8 {\n right: 66.66666667%;\n}\n.col-xs-pull-7 {\n right: 58.33333333%;\n}\n.col-xs-pull-6 {\n right: 50%;\n}\n.col-xs-pull-5 {\n right: 41.66666667%;\n}\n.col-xs-pull-4 {\n right: 33.33333333%;\n}\n.col-xs-pull-3 {\n right: 25%;\n}\n.col-xs-pull-2 {\n right: 16.66666667%;\n}\n.col-xs-pull-1 {\n right: 8.33333333%;\n}\n.col-xs-pull-0 {\n right: auto;\n}\n.col-xs-push-12 {\n left: 100%;\n}\n.col-xs-push-11 {\n left: 91.66666667%;\n}\n.col-xs-push-10 {\n left: 83.33333333%;\n}\n.col-xs-push-9 {\n left: 75%;\n}\n.col-xs-push-8 {\n left: 66.66666667%;\n}\n.col-xs-push-7 {\n left: 58.33333333%;\n}\n.col-xs-push-6 {\n left: 50%;\n}\n.col-xs-push-5 {\n left: 41.66666667%;\n}\n.col-xs-push-4 {\n left: 33.33333333%;\n}\n.col-xs-push-3 {\n left: 25%;\n}\n.col-xs-push-2 {\n left: 16.66666667%;\n}\n.col-xs-push-1 {\n left: 8.33333333%;\n}\n.col-xs-push-0 {\n left: auto;\n}\n.col-xs-offset-12 {\n margin-left: 100%;\n}\n.col-xs-offset-11 {\n margin-left: 91.66666667%;\n}\n.col-xs-offset-10 {\n margin-left: 83.33333333%;\n}\n.col-xs-offset-9 {\n margin-left: 75%;\n}\n.col-xs-offset-8 {\n margin-left: 66.66666667%;\n}\n.col-xs-offset-7 {\n margin-left: 58.33333333%;\n}\n.col-xs-offset-6 {\n margin-left: 50%;\n}\n.col-xs-offset-5 {\n margin-left: 41.66666667%;\n}\n.col-xs-offset-4 {\n margin-left: 33.33333333%;\n}\n.col-xs-offset-3 {\n margin-left: 25%;\n}\n.col-xs-offset-2 {\n margin-left: 16.66666667%;\n}\n.col-xs-offset-1 {\n margin-left: 8.33333333%;\n}\n.col-xs-offset-0 {\n margin-left: 0%;\n}\n@media (min-width: 768px) {\n .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {\n float: left;\n }\n .col-sm-12 {\n width: 100%;\n }\n .col-sm-11 {\n width: 91.66666667%;\n }\n .col-sm-10 {\n width: 83.33333333%;\n }\n .col-sm-9 {\n width: 75%;\n }\n .col-sm-8 {\n width: 66.66666667%;\n }\n .col-sm-7 {\n width: 58.33333333%;\n }\n .col-sm-6 {\n width: 50%;\n }\n .col-sm-5 {\n width: 41.66666667%;\n }\n .col-sm-4 {\n width: 33.33333333%;\n }\n .col-sm-3 {\n width: 25%;\n }\n .col-sm-2 {\n width: 16.66666667%;\n }\n .col-sm-1 {\n width: 8.33333333%;\n }\n .col-sm-pull-12 {\n right: 100%;\n }\n .col-sm-pull-11 {\n right: 91.66666667%;\n }\n .col-sm-pull-10 {\n right: 83.33333333%;\n }\n .col-sm-pull-9 {\n right: 75%;\n }\n .col-sm-pull-8 {\n right: 66.66666667%;\n }\n .col-sm-pull-7 {\n right: 58.33333333%;\n }\n .col-sm-pull-6 {\n right: 50%;\n }\n .col-sm-pull-5 {\n right: 41.66666667%;\n }\n .col-sm-pull-4 {\n right: 33.33333333%;\n }\n .col-sm-pull-3 {\n right: 25%;\n }\n .col-sm-pull-2 {\n right: 16.66666667%;\n }\n .col-sm-pull-1 {\n right: 8.33333333%;\n }\n .col-sm-pull-0 {\n right: auto;\n }\n .col-sm-push-12 {\n left: 100%;\n }\n .col-sm-push-11 {\n left: 91.66666667%;\n }\n .col-sm-push-10 {\n left: 83.33333333%;\n }\n .col-sm-push-9 {\n left: 75%;\n }\n .col-sm-push-8 {\n left: 66.66666667%;\n }\n .col-sm-push-7 {\n left: 58.33333333%;\n }\n .col-sm-push-6 {\n left: 50%;\n }\n .col-sm-push-5 {\n left: 41.66666667%;\n }\n .col-sm-push-4 {\n left: 33.33333333%;\n }\n .col-sm-push-3 {\n left: 25%;\n }\n .col-sm-push-2 {\n left: 16.66666667%;\n }\n .col-sm-push-1 {\n left: 8.33333333%;\n }\n .col-sm-push-0 {\n left: auto;\n }\n .col-sm-offset-12 {\n margin-left: 100%;\n }\n .col-sm-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-sm-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-sm-offset-9 {\n margin-left: 75%;\n }\n .col-sm-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-sm-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-sm-offset-6 {\n margin-left: 50%;\n }\n .col-sm-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-sm-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-sm-offset-3 {\n margin-left: 25%;\n }\n .col-sm-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-sm-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-sm-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 992px) {\n .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {\n float: left;\n }\n .col-md-12 {\n width: 100%;\n }\n .col-md-11 {\n width: 91.66666667%;\n }\n .col-md-10 {\n width: 83.33333333%;\n }\n .col-md-9 {\n width: 75%;\n }\n .col-md-8 {\n width: 66.66666667%;\n }\n .col-md-7 {\n width: 58.33333333%;\n }\n .col-md-6 {\n width: 50%;\n }\n .col-md-5 {\n width: 41.66666667%;\n }\n .col-md-4 {\n width: 33.33333333%;\n }\n .col-md-3 {\n width: 25%;\n }\n .col-md-2 {\n width: 16.66666667%;\n }\n .col-md-1 {\n width: 8.33333333%;\n }\n .col-md-pull-12 {\n right: 100%;\n }\n .col-md-pull-11 {\n right: 91.66666667%;\n }\n .col-md-pull-10 {\n right: 83.33333333%;\n }\n .col-md-pull-9 {\n right: 75%;\n }\n .col-md-pull-8 {\n right: 66.66666667%;\n }\n .col-md-pull-7 {\n right: 58.33333333%;\n }\n .col-md-pull-6 {\n right: 50%;\n }\n .col-md-pull-5 {\n right: 41.66666667%;\n }\n .col-md-pull-4 {\n right: 33.33333333%;\n }\n .col-md-pull-3 {\n right: 25%;\n }\n .col-md-pull-2 {\n right: 16.66666667%;\n }\n .col-md-pull-1 {\n right: 8.33333333%;\n }\n .col-md-pull-0 {\n right: auto;\n }\n .col-md-push-12 {\n left: 100%;\n }\n .col-md-push-11 {\n left: 91.66666667%;\n }\n .col-md-push-10 {\n left: 83.33333333%;\n }\n .col-md-push-9 {\n left: 75%;\n }\n .col-md-push-8 {\n left: 66.66666667%;\n }\n .col-md-push-7 {\n left: 58.33333333%;\n }\n .col-md-push-6 {\n left: 50%;\n }\n .col-md-push-5 {\n left: 41.66666667%;\n }\n .col-md-push-4 {\n left: 33.33333333%;\n }\n .col-md-push-3 {\n left: 25%;\n }\n .col-md-push-2 {\n left: 16.66666667%;\n }\n .col-md-push-1 {\n left: 8.33333333%;\n }\n .col-md-push-0 {\n left: auto;\n }\n .col-md-offset-12 {\n margin-left: 100%;\n }\n .col-md-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-md-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-md-offset-9 {\n margin-left: 75%;\n }\n .col-md-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-md-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-md-offset-6 {\n margin-left: 50%;\n }\n .col-md-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-md-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-md-offset-3 {\n margin-left: 25%;\n }\n .col-md-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-md-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-md-offset-0 {\n margin-left: 0%;\n }\n}\n@media (min-width: 1200px) {\n .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {\n float: left;\n }\n .col-lg-12 {\n width: 100%;\n }\n .col-lg-11 {\n width: 91.66666667%;\n }\n .col-lg-10 {\n width: 83.33333333%;\n }\n .col-lg-9 {\n width: 75%;\n }\n .col-lg-8 {\n width: 66.66666667%;\n }\n .col-lg-7 {\n width: 58.33333333%;\n }\n .col-lg-6 {\n width: 50%;\n }\n .col-lg-5 {\n width: 41.66666667%;\n }\n .col-lg-4 {\n width: 33.33333333%;\n }\n .col-lg-3 {\n width: 25%;\n }\n .col-lg-2 {\n width: 16.66666667%;\n }\n .col-lg-1 {\n width: 8.33333333%;\n }\n .col-lg-pull-12 {\n right: 100%;\n }\n .col-lg-pull-11 {\n right: 91.66666667%;\n }\n .col-lg-pull-10 {\n right: 83.33333333%;\n }\n .col-lg-pull-9 {\n right: 75%;\n }\n .col-lg-pull-8 {\n right: 66.66666667%;\n }\n .col-lg-pull-7 {\n right: 58.33333333%;\n }\n .col-lg-pull-6 {\n right: 50%;\n }\n .col-lg-pull-5 {\n right: 41.66666667%;\n }\n .col-lg-pull-4 {\n right: 33.33333333%;\n }\n .col-lg-pull-3 {\n right: 25%;\n }\n .col-lg-pull-2 {\n right: 16.66666667%;\n }\n .col-lg-pull-1 {\n right: 8.33333333%;\n }\n .col-lg-pull-0 {\n right: auto;\n }\n .col-lg-push-12 {\n left: 100%;\n }\n .col-lg-push-11 {\n left: 91.66666667%;\n }\n .col-lg-push-10 {\n left: 83.33333333%;\n }\n .col-lg-push-9 {\n left: 75%;\n }\n .col-lg-push-8 {\n left: 66.66666667%;\n }\n .col-lg-push-7 {\n left: 58.33333333%;\n }\n .col-lg-push-6 {\n left: 50%;\n }\n .col-lg-push-5 {\n left: 41.66666667%;\n }\n .col-lg-push-4 {\n left: 33.33333333%;\n }\n .col-lg-push-3 {\n left: 25%;\n }\n .col-lg-push-2 {\n left: 16.66666667%;\n }\n .col-lg-push-1 {\n left: 8.33333333%;\n }\n .col-lg-push-0 {\n left: auto;\n }\n .col-lg-offset-12 {\n margin-left: 100%;\n }\n .col-lg-offset-11 {\n margin-left: 91.66666667%;\n }\n .col-lg-offset-10 {\n margin-left: 83.33333333%;\n }\n .col-lg-offset-9 {\n margin-left: 75%;\n }\n .col-lg-offset-8 {\n margin-left: 66.66666667%;\n }\n .col-lg-offset-7 {\n margin-left: 58.33333333%;\n }\n .col-lg-offset-6 {\n margin-left: 50%;\n }\n .col-lg-offset-5 {\n margin-left: 41.66666667%;\n }\n .col-lg-offset-4 {\n margin-left: 33.33333333%;\n }\n .col-lg-offset-3 {\n margin-left: 25%;\n }\n .col-lg-offset-2 {\n margin-left: 16.66666667%;\n }\n .col-lg-offset-1 {\n margin-left: 8.33333333%;\n }\n .col-lg-offset-0 {\n margin-left: 0%;\n }\n}\ntable {\n background-color: transparent;\n}\ncaption {\n padding-top: 8px;\n padding-bottom: 8px;\n color: #777777;\n text-align: left;\n}\nth {\n text-align: left;\n}\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: 20px;\n}\n.table > thead > tr > th,\n.table > tbody > tr > th,\n.table > tfoot > tr > th,\n.table > thead > tr > td,\n.table > tbody > tr > td,\n.table > tfoot > tr > td {\n padding: 8px;\n line-height: 1.42857143;\n vertical-align: top;\n border-top: 1px solid #dddddd;\n}\n.table > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid #dddddd;\n}\n.table > caption + thead > tr:first-child > th,\n.table > colgroup + thead > tr:first-child > th,\n.table > thead:first-child > tr:first-child > th,\n.table > caption + thead > tr:first-child > td,\n.table > colgroup + thead > tr:first-child > td,\n.table > thead:first-child > tr:first-child > td {\n border-top: 0;\n}\n.table > tbody + tbody {\n border-top: 2px solid #dddddd;\n}\n.table .table {\n background-color: #ffffff;\n}\n.table-condensed > thead > tr > th,\n.table-condensed > tbody > tr > th,\n.table-condensed > tfoot > tr > th,\n.table-condensed > thead > tr > td,\n.table-condensed > tbody > tr > td,\n.table-condensed > tfoot > tr > td {\n padding: 5px;\n}\n.table-bordered {\n border: 1px solid #dddddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > tbody > tr > th,\n.table-bordered > tfoot > tr > th,\n.table-bordered > thead > tr > td,\n.table-bordered > tbody > tr > td,\n.table-bordered > tfoot > tr > td {\n border: 1px solid #dddddd;\n}\n.table-bordered > thead > tr > th,\n.table-bordered > thead > tr > td {\n border-bottom-width: 2px;\n}\n.table-striped > tbody > tr:nth-of-type(odd) {\n background-color: #f9f9f9;\n}\n.table-hover > tbody > tr:hover {\n background-color: #f5f5f5;\n}\ntable col[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-column;\n}\ntable td[class*=\"col-\"],\ntable th[class*=\"col-\"] {\n position: static;\n float: none;\n display: table-cell;\n}\n.table > thead > tr > td.active,\n.table > tbody > tr > td.active,\n.table > tfoot > tr > td.active,\n.table > thead > tr > th.active,\n.table > tbody > tr > th.active,\n.table > tfoot > tr > th.active,\n.table > thead > tr.active > td,\n.table > tbody > tr.active > td,\n.table > tfoot > tr.active > td,\n.table > thead > tr.active > th,\n.table > tbody > tr.active > th,\n.table > tfoot > tr.active > th {\n background-color: #f5f5f5;\n}\n.table-hover > tbody > tr > td.active:hover,\n.table-hover > tbody > tr > th.active:hover,\n.table-hover > tbody > tr.active:hover > td,\n.table-hover > tbody > tr:hover > .active,\n.table-hover > tbody > tr.active:hover > th {\n background-color: #e8e8e8;\n}\n.table > thead > tr > td.success,\n.table > tbody > tr > td.success,\n.table > tfoot > tr > td.success,\n.table > thead > tr > th.success,\n.table > tbody > tr > th.success,\n.table > tfoot > tr > th.success,\n.table > thead > tr.success > td,\n.table > tbody > tr.success > td,\n.table > tfoot > tr.success > td,\n.table > thead > tr.success > th,\n.table > tbody > tr.success > th,\n.table > tfoot > tr.success > th {\n background-color: #dff0d8;\n}\n.table-hover > tbody > tr > td.success:hover,\n.table-hover > tbody > tr > th.success:hover,\n.table-hover > tbody > tr.success:hover > td,\n.table-hover > tbody > tr:hover > .success,\n.table-hover > tbody > tr.success:hover > th {\n background-color: #d0e9c6;\n}\n.table > thead > tr > td.info,\n.table > tbody > tr > td.info,\n.table > tfoot > tr > td.info,\n.table > thead > tr > th.info,\n.table > tbody > tr > th.info,\n.table > tfoot > tr > th.info,\n.table > thead > tr.info > td,\n.table > tbody > tr.info > td,\n.table > tfoot > tr.info > td,\n.table > thead > tr.info > th,\n.table > tbody > tr.info > th,\n.table > tfoot > tr.info > th {\n background-color: #d9edf7;\n}\n.table-hover > tbody > tr > td.info:hover,\n.table-hover > tbody > tr > th.info:hover,\n.table-hover > tbody > tr.info:hover > td,\n.table-hover > tbody > tr:hover > .info,\n.table-hover > tbody > tr.info:hover > th {\n background-color: #c4e3f3;\n}\n.table > thead > tr > td.warning,\n.table > tbody > tr > td.warning,\n.table > tfoot > tr > td.warning,\n.table > thead > tr > th.warning,\n.table > tbody > tr > th.warning,\n.table > tfoot > tr > th.warning,\n.table > thead > tr.warning > td,\n.table > tbody > tr.warning > td,\n.table > tfoot > tr.warning > td,\n.table > thead > tr.warning > th,\n.table > tbody > tr.warning > th,\n.table > tfoot > tr.warning > th {\n background-color: #fcf8e3;\n}\n.table-hover > tbody > tr > td.warning:hover,\n.table-hover > tbody > tr > th.warning:hover,\n.table-hover > tbody > tr.warning:hover > td,\n.table-hover > tbody > tr:hover > .warning,\n.table-hover > tbody > tr.warning:hover > th {\n background-color: #faf2cc;\n}\n.table > thead > tr > td.danger,\n.table > tbody > tr > td.danger,\n.table > tfoot > tr > td.danger,\n.table > thead > tr > th.danger,\n.table > tbody > tr > th.danger,\n.table > tfoot > tr > th.danger,\n.table > thead > tr.danger > td,\n.table > tbody > tr.danger > td,\n.table > tfoot > tr.danger > td,\n.table > thead > tr.danger > th,\n.table > tbody > tr.danger > th,\n.table > tfoot > tr.danger > th {\n background-color: #f2dede;\n}\n.table-hover > tbody > tr > td.danger:hover,\n.table-hover > tbody > tr > th.danger:hover,\n.table-hover > tbody > tr.danger:hover > td,\n.table-hover > tbody > tr:hover > .danger,\n.table-hover > tbody > tr.danger:hover > th {\n background-color: #ebcccc;\n}\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%;\n}\n@media screen and (max-width: 767px) {\n .table-responsive {\n width: 100%;\n margin-bottom: 15px;\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid #dddddd;\n }\n .table-responsive > .table {\n margin-bottom: 0;\n }\n .table-responsive > .table > thead > tr > th,\n .table-responsive > .table > tbody > tr > th,\n .table-responsive > .table > tfoot > tr > th,\n .table-responsive > .table > thead > tr > td,\n .table-responsive > .table > tbody > tr > td,\n .table-responsive > .table > tfoot > tr > td {\n white-space: nowrap;\n }\n .table-responsive > .table-bordered {\n border: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:first-child,\n .table-responsive > .table-bordered > tbody > tr > th:first-child,\n .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n .table-responsive > .table-bordered > thead > tr > td:first-child,\n .table-responsive > .table-bordered > tbody > tr > td:first-child,\n .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n }\n .table-responsive > .table-bordered > thead > tr > th:last-child,\n .table-responsive > .table-bordered > tbody > tr > th:last-child,\n .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n .table-responsive > .table-bordered > thead > tr > td:last-child,\n .table-responsive > .table-bordered > tbody > tr > td:last-child,\n .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n }\n .table-responsive > .table-bordered > tbody > tr:last-child > th,\n .table-responsive > .table-bordered > tfoot > tr:last-child > th,\n .table-responsive > .table-bordered > tbody > tr:last-child > td,\n .table-responsive > .table-bordered > tfoot > tr:last-child > td {\n border-bottom: 0;\n }\n}\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n min-width: 0;\n}\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: 20px;\n font-size: 21px;\n line-height: inherit;\n color: #333333;\n border: 0;\n border-bottom: 1px solid #e5e5e5;\n}\nlabel {\n display: inline-block;\n max-width: 100%;\n margin-bottom: 5px;\n font-weight: bold;\n}\ninput[type=\"search\"] {\n -webkit-box-sizing: border-box;\n -moz-box-sizing: border-box;\n box-sizing: border-box;\n}\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9;\n line-height: normal;\n}\ninput[type=\"file\"] {\n display: block;\n}\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\nselect[multiple],\nselect[size] {\n height: auto;\n}\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\noutput {\n display: block;\n padding-top: 7px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n}\n.form-control {\n display: block;\n width: 100%;\n height: 34px;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n color: #555555;\n background-color: #ffffff;\n background-image: none;\n border: 1px solid #cccccc;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;\n}\n.form-control:focus {\n border-color: #66afe9;\n outline: 0;\n -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);\n}\n.form-control::-moz-placeholder {\n color: #999999;\n opacity: 1;\n}\n.form-control:-ms-input-placeholder {\n color: #999999;\n}\n.form-control::-webkit-input-placeholder {\n color: #999999;\n}\n.form-control[disabled],\n.form-control[readonly],\nfieldset[disabled] .form-control {\n background-color: #eeeeee;\n opacity: 1;\n}\n.form-control[disabled],\nfieldset[disabled] .form-control {\n cursor: not-allowed;\n}\ntextarea.form-control {\n height: auto;\n}\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"].form-control,\n input[type=\"time\"].form-control,\n input[type=\"datetime-local\"].form-control,\n input[type=\"month\"].form-control {\n line-height: 34px;\n }\n input[type=\"date\"].input-sm,\n input[type=\"time\"].input-sm,\n input[type=\"datetime-local\"].input-sm,\n input[type=\"month\"].input-sm,\n .input-group-sm input[type=\"date\"],\n .input-group-sm input[type=\"time\"],\n .input-group-sm input[type=\"datetime-local\"],\n .input-group-sm input[type=\"month\"] {\n line-height: 30px;\n }\n input[type=\"date\"].input-lg,\n input[type=\"time\"].input-lg,\n input[type=\"datetime-local\"].input-lg,\n input[type=\"month\"].input-lg,\n .input-group-lg input[type=\"date\"],\n .input-group-lg input[type=\"time\"],\n .input-group-lg input[type=\"datetime-local\"],\n .input-group-lg input[type=\"month\"] {\n line-height: 46px;\n }\n}\n.form-group {\n margin-bottom: 15px;\n}\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.radio label,\n.checkbox label {\n min-height: 20px;\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px;\n}\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px;\n}\ninput[type=\"radio\"][disabled],\ninput[type=\"checkbox\"][disabled],\ninput[type=\"radio\"].disabled,\ninput[type=\"checkbox\"].disabled,\nfieldset[disabled] input[type=\"radio\"],\nfieldset[disabled] input[type=\"checkbox\"] {\n cursor: not-allowed;\n}\n.radio-inline.disabled,\n.checkbox-inline.disabled,\nfieldset[disabled] .radio-inline,\nfieldset[disabled] .checkbox-inline {\n cursor: not-allowed;\n}\n.radio.disabled label,\n.checkbox.disabled label,\nfieldset[disabled] .radio label,\nfieldset[disabled] .checkbox label {\n cursor: not-allowed;\n}\n.form-control-static {\n padding-top: 7px;\n padding-bottom: 7px;\n margin-bottom: 0;\n min-height: 34px;\n}\n.form-control-static.input-lg,\n.form-control-static.input-sm {\n padding-left: 0;\n padding-right: 0;\n}\n.input-sm {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-sm {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-sm,\nselect[multiple].input-sm {\n height: auto;\n}\n.form-group-sm .form-control {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.form-group-sm select.form-control {\n height: 30px;\n line-height: 30px;\n}\n.form-group-sm textarea.form-control,\n.form-group-sm select[multiple].form-control {\n height: auto;\n}\n.form-group-sm .form-control-static {\n height: 30px;\n min-height: 32px;\n padding: 6px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.input-lg {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-lg {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-lg,\nselect[multiple].input-lg {\n height: auto;\n}\n.form-group-lg .form-control {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.form-group-lg select.form-control {\n height: 46px;\n line-height: 46px;\n}\n.form-group-lg textarea.form-control,\n.form-group-lg select[multiple].form-control {\n height: auto;\n}\n.form-group-lg .form-control-static {\n height: 46px;\n min-height: 38px;\n padding: 11px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.has-feedback {\n position: relative;\n}\n.has-feedback .form-control {\n padding-right: 42.5px;\n}\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2;\n display: block;\n width: 34px;\n height: 34px;\n line-height: 34px;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: 46px;\n height: 46px;\n line-height: 46px;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: 30px;\n height: 30px;\n line-height: 30px;\n}\n.has-success .help-block,\n.has-success .control-label,\n.has-success .radio,\n.has-success .checkbox,\n.has-success .radio-inline,\n.has-success .checkbox-inline,\n.has-success.radio label,\n.has-success.checkbox label,\n.has-success.radio-inline label,\n.has-success.checkbox-inline label {\n color: #3c763d;\n}\n.has-success .form-control {\n border-color: #3c763d;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-success .form-control:focus {\n border-color: #2b542c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #67b168;\n}\n.has-success .input-group-addon {\n color: #3c763d;\n border-color: #3c763d;\n background-color: #dff0d8;\n}\n.has-success .form-control-feedback {\n color: #3c763d;\n}\n.has-warning .help-block,\n.has-warning .control-label,\n.has-warning .radio,\n.has-warning .checkbox,\n.has-warning .radio-inline,\n.has-warning .checkbox-inline,\n.has-warning.radio label,\n.has-warning.checkbox label,\n.has-warning.radio-inline label,\n.has-warning.checkbox-inline label {\n color: #8a6d3b;\n}\n.has-warning .form-control {\n border-color: #8a6d3b;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-warning .form-control:focus {\n border-color: #66512c;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #c0a16b;\n}\n.has-warning .input-group-addon {\n color: #8a6d3b;\n border-color: #8a6d3b;\n background-color: #fcf8e3;\n}\n.has-warning .form-control-feedback {\n color: #8a6d3b;\n}\n.has-error .help-block,\n.has-error .control-label,\n.has-error .radio,\n.has-error .checkbox,\n.has-error .radio-inline,\n.has-error .checkbox-inline,\n.has-error.radio label,\n.has-error.checkbox label,\n.has-error.radio-inline label,\n.has-error.checkbox-inline label {\n color: #a94442;\n}\n.has-error .form-control {\n border-color: #a94442;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);\n}\n.has-error .form-control:focus {\n border-color: #843534;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #ce8483;\n}\n.has-error .input-group-addon {\n color: #a94442;\n border-color: #a94442;\n background-color: #f2dede;\n}\n.has-error .form-control-feedback {\n color: #a94442;\n}\n.has-feedback label ~ .form-control-feedback {\n top: 25px;\n}\n.has-feedback label.sr-only ~ .form-control-feedback {\n top: 0;\n}\n.help-block {\n display: block;\n margin-top: 5px;\n margin-bottom: 10px;\n color: #737373;\n}\n@media (min-width: 768px) {\n .form-inline .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .form-inline .form-control-static {\n display: inline-block;\n }\n .form-inline .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .form-inline .input-group .input-group-addon,\n .form-inline .input-group .input-group-btn,\n .form-inline .input-group .form-control {\n width: auto;\n }\n .form-inline .input-group > .form-control {\n width: 100%;\n }\n .form-inline .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio,\n .form-inline .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .form-inline .radio label,\n .form-inline .checkbox label {\n padding-left: 0;\n }\n .form-inline .radio input[type=\"radio\"],\n .form-inline .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .form-inline .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox,\n.form-horizontal .radio-inline,\n.form-horizontal .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: 7px;\n}\n.form-horizontal .radio,\n.form-horizontal .checkbox {\n min-height: 27px;\n}\n.form-horizontal .form-group {\n margin-left: -15px;\n margin-right: -15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: 7px;\n }\n}\n.form-horizontal .has-feedback .form-control-feedback {\n right: 15px;\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-lg .control-label {\n padding-top: 14.333333px;\n font-size: 18px;\n }\n}\n@media (min-width: 768px) {\n .form-horizontal .form-group-sm .control-label {\n padding-top: 6px;\n font-size: 12px;\n }\n}\n.btn {\n display: inline-block;\n margin-bottom: 0;\n font-weight: normal;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none;\n border: 1px solid transparent;\n white-space: nowrap;\n padding: 6px 12px;\n font-size: 14px;\n line-height: 1.42857143;\n border-radius: 4px;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n}\n.btn:focus,\n.btn:active:focus,\n.btn.active:focus,\n.btn.focus,\n.btn:active.focus,\n.btn.active.focus {\n outline: thin dotted;\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n.btn:hover,\n.btn:focus,\n.btn.focus {\n color: #333333;\n text-decoration: none;\n}\n.btn:active,\n.btn.active {\n outline: 0;\n background-image: none;\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn.disabled,\n.btn[disabled],\nfieldset[disabled] .btn {\n cursor: not-allowed;\n opacity: 0.65;\n filter: alpha(opacity=65);\n -webkit-box-shadow: none;\n box-shadow: none;\n}\na.btn.disabled,\nfieldset[disabled] a.btn {\n pointer-events: none;\n}\n.btn-default {\n color: #333333;\n background-color: #ffffff;\n border-color: #cccccc;\n}\n.btn-default:focus,\n.btn-default.focus {\n color: #333333;\n background-color: #e6e6e6;\n border-color: #8c8c8c;\n}\n.btn-default:hover {\n color: #333333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n color: #333333;\n background-color: #e6e6e6;\n border-color: #adadad;\n}\n.btn-default:active:hover,\n.btn-default.active:hover,\n.open > .dropdown-toggle.btn-default:hover,\n.btn-default:active:focus,\n.btn-default.active:focus,\n.open > .dropdown-toggle.btn-default:focus,\n.btn-default:active.focus,\n.btn-default.active.focus,\n.open > .dropdown-toggle.btn-default.focus {\n color: #333333;\n background-color: #d4d4d4;\n border-color: #8c8c8c;\n}\n.btn-default:active,\n.btn-default.active,\n.open > .dropdown-toggle.btn-default {\n background-image: none;\n}\n.btn-default.disabled,\n.btn-default[disabled],\nfieldset[disabled] .btn-default,\n.btn-default.disabled:hover,\n.btn-default[disabled]:hover,\nfieldset[disabled] .btn-default:hover,\n.btn-default.disabled:focus,\n.btn-default[disabled]:focus,\nfieldset[disabled] .btn-default:focus,\n.btn-default.disabled.focus,\n.btn-default[disabled].focus,\nfieldset[disabled] .btn-default.focus,\n.btn-default.disabled:active,\n.btn-default[disabled]:active,\nfieldset[disabled] .btn-default:active,\n.btn-default.disabled.active,\n.btn-default[disabled].active,\nfieldset[disabled] .btn-default.active {\n background-color: #ffffff;\n border-color: #cccccc;\n}\n.btn-default .badge {\n color: #ffffff;\n background-color: #333333;\n}\n.btn-primary {\n color: #ffffff;\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary:focus,\n.btn-primary.focus {\n color: #ffffff;\n background-color: #286090;\n border-color: #122b40;\n}\n.btn-primary:hover {\n color: #ffffff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n color: #ffffff;\n background-color: #286090;\n border-color: #204d74;\n}\n.btn-primary:active:hover,\n.btn-primary.active:hover,\n.open > .dropdown-toggle.btn-primary:hover,\n.btn-primary:active:focus,\n.btn-primary.active:focus,\n.open > .dropdown-toggle.btn-primary:focus,\n.btn-primary:active.focus,\n.btn-primary.active.focus,\n.open > .dropdown-toggle.btn-primary.focus {\n color: #ffffff;\n background-color: #204d74;\n border-color: #122b40;\n}\n.btn-primary:active,\n.btn-primary.active,\n.open > .dropdown-toggle.btn-primary {\n background-image: none;\n}\n.btn-primary.disabled,\n.btn-primary[disabled],\nfieldset[disabled] .btn-primary,\n.btn-primary.disabled:hover,\n.btn-primary[disabled]:hover,\nfieldset[disabled] .btn-primary:hover,\n.btn-primary.disabled:focus,\n.btn-primary[disabled]:focus,\nfieldset[disabled] .btn-primary:focus,\n.btn-primary.disabled.focus,\n.btn-primary[disabled].focus,\nfieldset[disabled] .btn-primary.focus,\n.btn-primary.disabled:active,\n.btn-primary[disabled]:active,\nfieldset[disabled] .btn-primary:active,\n.btn-primary.disabled.active,\n.btn-primary[disabled].active,\nfieldset[disabled] .btn-primary.active {\n background-color: #337ab7;\n border-color: #2e6da4;\n}\n.btn-primary .badge {\n color: #337ab7;\n background-color: #ffffff;\n}\n.btn-success {\n color: #ffffff;\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success:focus,\n.btn-success.focus {\n color: #ffffff;\n background-color: #449d44;\n border-color: #255625;\n}\n.btn-success:hover {\n color: #ffffff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n color: #ffffff;\n background-color: #449d44;\n border-color: #398439;\n}\n.btn-success:active:hover,\n.btn-success.active:hover,\n.open > .dropdown-toggle.btn-success:hover,\n.btn-success:active:focus,\n.btn-success.active:focus,\n.open > .dropdown-toggle.btn-success:focus,\n.btn-success:active.focus,\n.btn-success.active.focus,\n.open > .dropdown-toggle.btn-success.focus {\n color: #ffffff;\n background-color: #398439;\n border-color: #255625;\n}\n.btn-success:active,\n.btn-success.active,\n.open > .dropdown-toggle.btn-success {\n background-image: none;\n}\n.btn-success.disabled,\n.btn-success[disabled],\nfieldset[disabled] .btn-success,\n.btn-success.disabled:hover,\n.btn-success[disabled]:hover,\nfieldset[disabled] .btn-success:hover,\n.btn-success.disabled:focus,\n.btn-success[disabled]:focus,\nfieldset[disabled] .btn-success:focus,\n.btn-success.disabled.focus,\n.btn-success[disabled].focus,\nfieldset[disabled] .btn-success.focus,\n.btn-success.disabled:active,\n.btn-success[disabled]:active,\nfieldset[disabled] .btn-success:active,\n.btn-success.disabled.active,\n.btn-success[disabled].active,\nfieldset[disabled] .btn-success.active {\n background-color: #5cb85c;\n border-color: #4cae4c;\n}\n.btn-success .badge {\n color: #5cb85c;\n background-color: #ffffff;\n}\n.btn-info {\n color: #ffffff;\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info:focus,\n.btn-info.focus {\n color: #ffffff;\n background-color: #31b0d5;\n border-color: #1b6d85;\n}\n.btn-info:hover {\n color: #ffffff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n color: #ffffff;\n background-color: #31b0d5;\n border-color: #269abc;\n}\n.btn-info:active:hover,\n.btn-info.active:hover,\n.open > .dropdown-toggle.btn-info:hover,\n.btn-info:active:focus,\n.btn-info.active:focus,\n.open > .dropdown-toggle.btn-info:focus,\n.btn-info:active.focus,\n.btn-info.active.focus,\n.open > .dropdown-toggle.btn-info.focus {\n color: #ffffff;\n background-color: #269abc;\n border-color: #1b6d85;\n}\n.btn-info:active,\n.btn-info.active,\n.open > .dropdown-toggle.btn-info {\n background-image: none;\n}\n.btn-info.disabled,\n.btn-info[disabled],\nfieldset[disabled] .btn-info,\n.btn-info.disabled:hover,\n.btn-info[disabled]:hover,\nfieldset[disabled] .btn-info:hover,\n.btn-info.disabled:focus,\n.btn-info[disabled]:focus,\nfieldset[disabled] .btn-info:focus,\n.btn-info.disabled.focus,\n.btn-info[disabled].focus,\nfieldset[disabled] .btn-info.focus,\n.btn-info.disabled:active,\n.btn-info[disabled]:active,\nfieldset[disabled] .btn-info:active,\n.btn-info.disabled.active,\n.btn-info[disabled].active,\nfieldset[disabled] .btn-info.active {\n background-color: #5bc0de;\n border-color: #46b8da;\n}\n.btn-info .badge {\n color: #5bc0de;\n background-color: #ffffff;\n}\n.btn-warning {\n color: #ffffff;\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning:focus,\n.btn-warning.focus {\n color: #ffffff;\n background-color: #ec971f;\n border-color: #985f0d;\n}\n.btn-warning:hover {\n color: #ffffff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n color: #ffffff;\n background-color: #ec971f;\n border-color: #d58512;\n}\n.btn-warning:active:hover,\n.btn-warning.active:hover,\n.open > .dropdown-toggle.btn-warning:hover,\n.btn-warning:active:focus,\n.btn-warning.active:focus,\n.open > .dropdown-toggle.btn-warning:focus,\n.btn-warning:active.focus,\n.btn-warning.active.focus,\n.open > .dropdown-toggle.btn-warning.focus {\n color: #ffffff;\n background-color: #d58512;\n border-color: #985f0d;\n}\n.btn-warning:active,\n.btn-warning.active,\n.open > .dropdown-toggle.btn-warning {\n background-image: none;\n}\n.btn-warning.disabled,\n.btn-warning[disabled],\nfieldset[disabled] .btn-warning,\n.btn-warning.disabled:hover,\n.btn-warning[disabled]:hover,\nfieldset[disabled] .btn-warning:hover,\n.btn-warning.disabled:focus,\n.btn-warning[disabled]:focus,\nfieldset[disabled] .btn-warning:focus,\n.btn-warning.disabled.focus,\n.btn-warning[disabled].focus,\nfieldset[disabled] .btn-warning.focus,\n.btn-warning.disabled:active,\n.btn-warning[disabled]:active,\nfieldset[disabled] .btn-warning:active,\n.btn-warning.disabled.active,\n.btn-warning[disabled].active,\nfieldset[disabled] .btn-warning.active {\n background-color: #f0ad4e;\n border-color: #eea236;\n}\n.btn-warning .badge {\n color: #f0ad4e;\n background-color: #ffffff;\n}\n.btn-danger {\n color: #ffffff;\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger:focus,\n.btn-danger.focus {\n color: #ffffff;\n background-color: #c9302c;\n border-color: #761c19;\n}\n.btn-danger:hover {\n color: #ffffff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n color: #ffffff;\n background-color: #c9302c;\n border-color: #ac2925;\n}\n.btn-danger:active:hover,\n.btn-danger.active:hover,\n.open > .dropdown-toggle.btn-danger:hover,\n.btn-danger:active:focus,\n.btn-danger.active:focus,\n.open > .dropdown-toggle.btn-danger:focus,\n.btn-danger:active.focus,\n.btn-danger.active.focus,\n.open > .dropdown-toggle.btn-danger.focus {\n color: #ffffff;\n background-color: #ac2925;\n border-color: #761c19;\n}\n.btn-danger:active,\n.btn-danger.active,\n.open > .dropdown-toggle.btn-danger {\n background-image: none;\n}\n.btn-danger.disabled,\n.btn-danger[disabled],\nfieldset[disabled] .btn-danger,\n.btn-danger.disabled:hover,\n.btn-danger[disabled]:hover,\nfieldset[disabled] .btn-danger:hover,\n.btn-danger.disabled:focus,\n.btn-danger[disabled]:focus,\nfieldset[disabled] .btn-danger:focus,\n.btn-danger.disabled.focus,\n.btn-danger[disabled].focus,\nfieldset[disabled] .btn-danger.focus,\n.btn-danger.disabled:active,\n.btn-danger[disabled]:active,\nfieldset[disabled] .btn-danger:active,\n.btn-danger.disabled.active,\n.btn-danger[disabled].active,\nfieldset[disabled] .btn-danger.active {\n background-color: #d9534f;\n border-color: #d43f3a;\n}\n.btn-danger .badge {\n color: #d9534f;\n background-color: #ffffff;\n}\n.btn-link {\n color: #337ab7;\n font-weight: normal;\n border-radius: 0;\n}\n.btn-link,\n.btn-link:active,\n.btn-link.active,\n.btn-link[disabled],\nfieldset[disabled] .btn-link {\n background-color: transparent;\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn-link,\n.btn-link:hover,\n.btn-link:focus,\n.btn-link:active {\n border-color: transparent;\n}\n.btn-link:hover,\n.btn-link:focus {\n color: #23527c;\n text-decoration: underline;\n background-color: transparent;\n}\n.btn-link[disabled]:hover,\nfieldset[disabled] .btn-link:hover,\n.btn-link[disabled]:focus,\nfieldset[disabled] .btn-link:focus {\n color: #777777;\n text-decoration: none;\n}\n.btn-lg,\n.btn-group-lg > .btn {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\n.btn-sm,\n.btn-group-sm > .btn {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-xs,\n.btn-group-xs > .btn {\n padding: 1px 5px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\n.btn-block {\n display: block;\n width: 100%;\n}\n.btn-block + .btn-block {\n margin-top: 5px;\n}\ninput[type=\"submit\"].btn-block,\ninput[type=\"reset\"].btn-block,\ninput[type=\"button\"].btn-block {\n width: 100%;\n}\n.fade {\n opacity: 0;\n -webkit-transition: opacity 0.15s linear;\n -o-transition: opacity 0.15s linear;\n transition: opacity 0.15s linear;\n}\n.fade.in {\n opacity: 1;\n}\n.collapse {\n display: none;\n}\n.collapse.in {\n display: block;\n}\ntr.collapse.in {\n display: table-row;\n}\ntbody.collapse.in {\n display: table-row-group;\n}\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n -webkit-transition-property: height, visibility;\n transition-property: height, visibility;\n -webkit-transition-duration: 0.35s;\n transition-duration: 0.35s;\n -webkit-transition-timing-function: ease;\n transition-timing-function: ease;\n}\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: 4px dashed;\n border-top: 4px solid \\9;\n border-right: 4px solid transparent;\n border-left: 4px solid transparent;\n}\n.dropup,\n.dropdown {\n position: relative;\n}\n.dropdown-toggle:focus {\n outline: 0;\n}\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: 1000;\n display: none;\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0;\n list-style: none;\n font-size: 14px;\n text-align: left;\n background-color: #ffffff;\n border: 1px solid #cccccc;\n border: 1px solid rgba(0, 0, 0, 0.15);\n border-radius: 4px;\n -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);\n background-clip: padding-box;\n}\n.dropdown-menu.pull-right {\n right: 0;\n left: auto;\n}\n.dropdown-menu .divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.dropdown-menu > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: 1.42857143;\n color: #333333;\n white-space: nowrap;\n}\n.dropdown-menu > li > a:hover,\n.dropdown-menu > li > a:focus {\n text-decoration: none;\n color: #262626;\n background-color: #f5f5f5;\n}\n.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n color: #ffffff;\n text-decoration: none;\n outline: 0;\n background-color: #337ab7;\n}\n.dropdown-menu > .disabled > a,\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n color: #777777;\n}\n.dropdown-menu > .disabled > a:hover,\n.dropdown-menu > .disabled > a:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none;\n filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);\n cursor: not-allowed;\n}\n.open > .dropdown-menu {\n display: block;\n}\n.open > a {\n outline: 0;\n}\n.dropdown-menu-right {\n left: auto;\n right: 0;\n}\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: 12px;\n line-height: 1.42857143;\n color: #777777;\n white-space: nowrap;\n}\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: 990;\n}\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n.dropup .caret,\n.navbar-fixed-bottom .dropdown .caret {\n border-top: 0;\n border-bottom: 4px dashed;\n border-bottom: 4px solid \\9;\n content: \"\";\n}\n.dropup .dropdown-menu,\n.navbar-fixed-bottom .dropdown .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n}\n@media (min-width: 768px) {\n .navbar-right .dropdown-menu {\n left: auto;\n right: 0;\n }\n .navbar-right .dropdown-menu-left {\n left: 0;\n right: auto;\n }\n}\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle;\n}\n.btn-group > .btn,\n.btn-group-vertical > .btn {\n position: relative;\n float: left;\n}\n.btn-group > .btn:hover,\n.btn-group-vertical > .btn:hover,\n.btn-group > .btn:focus,\n.btn-group-vertical > .btn:focus,\n.btn-group > .btn:active,\n.btn-group-vertical > .btn:active,\n.btn-group > .btn.active,\n.btn-group-vertical > .btn.active {\n z-index: 2;\n}\n.btn-group .btn + .btn,\n.btn-group .btn + .btn-group,\n.btn-group .btn-group + .btn,\n.btn-group .btn-group + .btn-group {\n margin-left: -1px;\n}\n.btn-toolbar {\n margin-left: -5px;\n}\n.btn-toolbar .btn,\n.btn-toolbar .btn-group,\n.btn-toolbar .input-group {\n float: left;\n}\n.btn-toolbar > .btn,\n.btn-toolbar > .btn-group,\n.btn-toolbar > .input-group {\n margin-left: 5px;\n}\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n.btn-group > .btn:first-child {\n margin-left: 0;\n}\n.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n.btn-group.open .dropdown-toggle {\n -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);\n}\n.btn-group.open .dropdown-toggle.btn-link {\n -webkit-box-shadow: none;\n box-shadow: none;\n}\n.btn .caret {\n margin-left: 0;\n}\n.btn-lg .caret {\n border-width: 5px 5px 0;\n border-bottom-width: 0;\n}\n.dropup .btn-lg .caret {\n border-width: 0 5px 5px;\n}\n.btn-group-vertical > .btn,\n.btn-group-vertical > .btn-group,\n.btn-group-vertical > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n}\n.btn-group-vertical > .btn-group > .btn {\n float: none;\n}\n.btn-group-vertical > .btn + .btn,\n.btn-group-vertical > .btn + .btn-group,\n.btn-group-vertical > .btn-group + .btn,\n.btn-group-vertical > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n}\n.btn-group-vertical > .btn:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.btn-group-vertical > .btn:first-child:not(:last-child) {\n border-top-right-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn:last-child:not(:first-child) {\n border-bottom-left-radius: 4px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,\n.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n}\n.btn-group-justified > .btn,\n.btn-group-justified > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n}\n.btn-group-justified > .btn-group .btn {\n width: 100%;\n}\n.btn-group-justified > .btn-group .dropdown-menu {\n left: auto;\n}\n[data-toggle=\"buttons\"] > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"radio\"],\n[data-toggle=\"buttons\"] > .btn input[type=\"checkbox\"],\n[data-toggle=\"buttons\"] > .btn-group > .btn input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0, 0, 0, 0);\n pointer-events: none;\n}\n.input-group {\n position: relative;\n display: table;\n border-collapse: separate;\n}\n.input-group[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n}\n.input-group .form-control {\n position: relative;\n z-index: 2;\n float: left;\n width: 100%;\n margin-bottom: 0;\n}\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n border-radius: 6px;\n}\nselect.input-group-lg > .form-control,\nselect.input-group-lg > .input-group-addon,\nselect.input-group-lg > .input-group-btn > .btn {\n height: 46px;\n line-height: 46px;\n}\ntextarea.input-group-lg > .form-control,\ntextarea.input-group-lg > .input-group-addon,\ntextarea.input-group-lg > .input-group-btn > .btn,\nselect[multiple].input-group-lg > .form-control,\nselect[multiple].input-group-lg > .input-group-addon,\nselect[multiple].input-group-lg > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n border-radius: 3px;\n}\nselect.input-group-sm > .form-control,\nselect.input-group-sm > .input-group-addon,\nselect.input-group-sm > .input-group-btn > .btn {\n height: 30px;\n line-height: 30px;\n}\ntextarea.input-group-sm > .form-control,\ntextarea.input-group-sm > .input-group-addon,\ntextarea.input-group-sm > .input-group-btn > .btn,\nselect[multiple].input-group-sm > .form-control,\nselect[multiple].input-group-sm > .input-group-addon,\nselect[multiple].input-group-sm > .input-group-btn > .btn {\n height: auto;\n}\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n}\n.input-group-addon:not(:first-child):not(:last-child),\n.input-group-btn:not(:first-child):not(:last-child),\n.input-group .form-control:not(:first-child):not(:last-child) {\n border-radius: 0;\n}\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle;\n}\n.input-group-addon {\n padding: 6px 12px;\n font-size: 14px;\n font-weight: normal;\n line-height: 1;\n color: #555555;\n text-align: center;\n background-color: #eeeeee;\n border: 1px solid #cccccc;\n border-radius: 4px;\n}\n.input-group-addon.input-sm {\n padding: 5px 10px;\n font-size: 12px;\n border-radius: 3px;\n}\n.input-group-addon.input-lg {\n padding: 10px 16px;\n font-size: 18px;\n border-radius: 6px;\n}\n.input-group-addon input[type=\"radio\"],\n.input-group-addon input[type=\"checkbox\"] {\n margin-top: 0;\n}\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n border-bottom-right-radius: 0;\n border-top-right-radius: 0;\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n border-bottom-left-radius: 0;\n border-top-left-radius: 0;\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n.input-group-btn {\n position: relative;\n font-size: 0;\n white-space: nowrap;\n}\n.input-group-btn > .btn {\n position: relative;\n}\n.input-group-btn > .btn + .btn {\n margin-left: -1px;\n}\n.input-group-btn > .btn:hover,\n.input-group-btn > .btn:focus,\n.input-group-btn > .btn:active {\n z-index: 2;\n}\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group {\n margin-right: -1px;\n}\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group {\n z-index: 2;\n margin-left: -1px;\n}\n.nav {\n margin-bottom: 0;\n padding-left: 0;\n list-style: none;\n}\n.nav > li {\n position: relative;\n display: block;\n}\n.nav > li > a {\n position: relative;\n display: block;\n padding: 10px 15px;\n}\n.nav > li > a:hover,\n.nav > li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.nav > li.disabled > a {\n color: #777777;\n}\n.nav > li.disabled > a:hover,\n.nav > li.disabled > a:focus {\n color: #777777;\n text-decoration: none;\n background-color: transparent;\n cursor: not-allowed;\n}\n.nav .open > a,\n.nav .open > a:hover,\n.nav .open > a:focus {\n background-color: #eeeeee;\n border-color: #337ab7;\n}\n.nav .nav-divider {\n height: 1px;\n margin: 9px 0;\n overflow: hidden;\n background-color: #e5e5e5;\n}\n.nav > li > a > img {\n max-width: none;\n}\n.nav-tabs {\n border-bottom: 1px solid #dddddd;\n}\n.nav-tabs > li {\n float: left;\n margin-bottom: -1px;\n}\n.nav-tabs > li > a {\n margin-right: 2px;\n line-height: 1.42857143;\n border: 1px solid transparent;\n border-radius: 4px 4px 0 0;\n}\n.nav-tabs > li > a:hover {\n border-color: #eeeeee #eeeeee #dddddd;\n}\n.nav-tabs > li.active > a,\n.nav-tabs > li.active > a:hover,\n.nav-tabs > li.active > a:focus {\n color: #555555;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-bottom-color: transparent;\n cursor: default;\n}\n.nav-tabs.nav-justified {\n width: 100%;\n border-bottom: 0;\n}\n.nav-tabs.nav-justified > li {\n float: none;\n}\n.nav-tabs.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-tabs.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-tabs.nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs.nav-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs.nav-justified > .active > a,\n.nav-tabs.nav-justified > .active > a:hover,\n.nav-tabs.nav-justified > .active > a:focus {\n border: 1px solid #dddddd;\n}\n@media (min-width: 768px) {\n .nav-tabs.nav-justified > li > a {\n border-bottom: 1px solid #dddddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs.nav-justified > .active > a,\n .nav-tabs.nav-justified > .active > a:hover,\n .nav-tabs.nav-justified > .active > a:focus {\n border-bottom-color: #ffffff;\n }\n}\n.nav-pills > li {\n float: left;\n}\n.nav-pills > li > a {\n border-radius: 4px;\n}\n.nav-pills > li + li {\n margin-left: 2px;\n}\n.nav-pills > li.active > a,\n.nav-pills > li.active > a:hover,\n.nav-pills > li.active > a:focus {\n color: #ffffff;\n background-color: #337ab7;\n}\n.nav-stacked > li {\n float: none;\n}\n.nav-stacked > li + li {\n margin-top: 2px;\n margin-left: 0;\n}\n.nav-justified {\n width: 100%;\n}\n.nav-justified > li {\n float: none;\n}\n.nav-justified > li > a {\n text-align: center;\n margin-bottom: 5px;\n}\n.nav-justified > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n}\n@media (min-width: 768px) {\n .nav-justified > li {\n display: table-cell;\n width: 1%;\n }\n .nav-justified > li > a {\n margin-bottom: 0;\n }\n}\n.nav-tabs-justified {\n border-bottom: 0;\n}\n.nav-tabs-justified > li > a {\n margin-right: 0;\n border-radius: 4px;\n}\n.nav-tabs-justified > .active > a,\n.nav-tabs-justified > .active > a:hover,\n.nav-tabs-justified > .active > a:focus {\n border: 1px solid #dddddd;\n}\n@media (min-width: 768px) {\n .nav-tabs-justified > li > a {\n border-bottom: 1px solid #dddddd;\n border-radius: 4px 4px 0 0;\n }\n .nav-tabs-justified > .active > a,\n .nav-tabs-justified > .active > a:hover,\n .nav-tabs-justified > .active > a:focus {\n border-bottom-color: #ffffff;\n }\n}\n.tab-content > .tab-pane {\n display: none;\n}\n.tab-content > .active {\n display: block;\n}\n.nav-tabs .dropdown-menu {\n margin-top: -1px;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar {\n position: relative;\n min-height: 50px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n}\n@media (min-width: 768px) {\n .navbar {\n border-radius: 4px;\n }\n}\n@media (min-width: 768px) {\n .navbar-header {\n float: left;\n }\n}\n.navbar-collapse {\n overflow-x: visible;\n padding-right: 15px;\n padding-left: 15px;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);\n -webkit-overflow-scrolling: touch;\n}\n.navbar-collapse.in {\n overflow-y: auto;\n}\n@media (min-width: 768px) {\n .navbar-collapse {\n width: auto;\n border-top: 0;\n box-shadow: none;\n }\n .navbar-collapse.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0;\n overflow: visible !important;\n }\n .navbar-collapse.in {\n overflow-y: visible;\n }\n .navbar-fixed-top .navbar-collapse,\n .navbar-static-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n padding-left: 0;\n padding-right: 0;\n }\n}\n.navbar-fixed-top .navbar-collapse,\n.navbar-fixed-bottom .navbar-collapse {\n max-height: 340px;\n}\n@media (max-device-width: 480px) and (orientation: landscape) {\n .navbar-fixed-top .navbar-collapse,\n .navbar-fixed-bottom .navbar-collapse {\n max-height: 200px;\n }\n}\n.container > .navbar-header,\n.container-fluid > .navbar-header,\n.container > .navbar-collapse,\n.container-fluid > .navbar-collapse {\n margin-right: -15px;\n margin-left: -15px;\n}\n@media (min-width: 768px) {\n .container > .navbar-header,\n .container-fluid > .navbar-header,\n .container > .navbar-collapse,\n .container-fluid > .navbar-collapse {\n margin-right: 0;\n margin-left: 0;\n }\n}\n.navbar-static-top {\n z-index: 1000;\n border-width: 0 0 1px;\n}\n@media (min-width: 768px) {\n .navbar-static-top {\n border-radius: 0;\n }\n}\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: 1030;\n}\n@media (min-width: 768px) {\n .navbar-fixed-top,\n .navbar-fixed-bottom {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0;\n border-width: 1px 0 0;\n}\n.navbar-brand {\n float: left;\n padding: 15px 15px;\n font-size: 18px;\n line-height: 20px;\n height: 50px;\n}\n.navbar-brand:hover,\n.navbar-brand:focus {\n text-decoration: none;\n}\n.navbar-brand > img {\n display: block;\n}\n@media (min-width: 768px) {\n .navbar > .container .navbar-brand,\n .navbar > .container-fluid .navbar-brand {\n margin-left: -15px;\n }\n}\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: 15px;\n padding: 9px 10px;\n margin-top: 8px;\n margin-bottom: 8px;\n background-color: transparent;\n background-image: none;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.navbar-toggle:focus {\n outline: 0;\n}\n.navbar-toggle .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n}\n.navbar-toggle .icon-bar + .icon-bar {\n margin-top: 4px;\n}\n@media (min-width: 768px) {\n .navbar-toggle {\n display: none;\n }\n}\n.navbar-nav {\n margin: 7.5px -15px;\n}\n.navbar-nav > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: 20px;\n}\n@media (max-width: 767px) {\n .navbar-nav .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n }\n .navbar-nav .open .dropdown-menu > li > a,\n .navbar-nav .open .dropdown-menu .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n .navbar-nav .open .dropdown-menu > li > a {\n line-height: 20px;\n }\n .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-nav .open .dropdown-menu > li > a:focus {\n background-image: none;\n }\n}\n@media (min-width: 768px) {\n .navbar-nav {\n float: left;\n margin: 0;\n }\n .navbar-nav > li {\n float: left;\n }\n .navbar-nav > li > a {\n padding-top: 15px;\n padding-bottom: 15px;\n }\n}\n.navbar-form {\n margin-left: -15px;\n margin-right: -15px;\n padding: 10px 15px;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);\n margin-top: 8px;\n margin-bottom: 8px;\n}\n@media (min-width: 768px) {\n .navbar-form .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .form-control {\n display: inline-block;\n width: auto;\n vertical-align: middle;\n }\n .navbar-form .form-control-static {\n display: inline-block;\n }\n .navbar-form .input-group {\n display: inline-table;\n vertical-align: middle;\n }\n .navbar-form .input-group .input-group-addon,\n .navbar-form .input-group .input-group-btn,\n .navbar-form .input-group .form-control {\n width: auto;\n }\n .navbar-form .input-group > .form-control {\n width: 100%;\n }\n .navbar-form .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio,\n .navbar-form .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n }\n .navbar-form .radio label,\n .navbar-form .checkbox label {\n padding-left: 0;\n }\n .navbar-form .radio input[type=\"radio\"],\n .navbar-form .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n .navbar-form .has-feedback .form-control-feedback {\n top: 0;\n }\n}\n@media (max-width: 767px) {\n .navbar-form .form-group {\n margin-bottom: 5px;\n }\n .navbar-form .form-group:last-child {\n margin-bottom: 0;\n }\n}\n@media (min-width: 768px) {\n .navbar-form {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n -webkit-box-shadow: none;\n box-shadow: none;\n }\n}\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n border-bottom-right-radius: 0;\n border-bottom-left-radius: 0;\n}\n.navbar-btn {\n margin-top: 8px;\n margin-bottom: 8px;\n}\n.navbar-btn.btn-sm {\n margin-top: 10px;\n margin-bottom: 10px;\n}\n.navbar-btn.btn-xs {\n margin-top: 14px;\n margin-bottom: 14px;\n}\n.navbar-text {\n margin-top: 15px;\n margin-bottom: 15px;\n}\n@media (min-width: 768px) {\n .navbar-text {\n float: left;\n margin-left: 15px;\n margin-right: 15px;\n }\n}\n@media (min-width: 768px) {\n .navbar-left {\n float: left !important;\n }\n .navbar-right {\n float: right !important;\n margin-right: -15px;\n }\n .navbar-right ~ .navbar-right {\n margin-right: 0;\n }\n}\n.navbar-default {\n background-color: #f8f8f8;\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-brand {\n color: #777777;\n}\n.navbar-default .navbar-brand:hover,\n.navbar-default .navbar-brand:focus {\n color: #5e5e5e;\n background-color: transparent;\n}\n.navbar-default .navbar-text {\n color: #777777;\n}\n.navbar-default .navbar-nav > li > a {\n color: #777777;\n}\n.navbar-default .navbar-nav > li > a:hover,\n.navbar-default .navbar-nav > li > a:focus {\n color: #333333;\n background-color: transparent;\n}\n.navbar-default .navbar-nav > .active > a,\n.navbar-default .navbar-nav > .active > a:hover,\n.navbar-default .navbar-nav > .active > a:focus {\n color: #555555;\n background-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .disabled > a,\n.navbar-default .navbar-nav > .disabled > a:hover,\n.navbar-default .navbar-nav > .disabled > a:focus {\n color: #cccccc;\n background-color: transparent;\n}\n.navbar-default .navbar-toggle {\n border-color: #dddddd;\n}\n.navbar-default .navbar-toggle:hover,\n.navbar-default .navbar-toggle:focus {\n background-color: #dddddd;\n}\n.navbar-default .navbar-toggle .icon-bar {\n background-color: #888888;\n}\n.navbar-default .navbar-collapse,\n.navbar-default .navbar-form {\n border-color: #e7e7e7;\n}\n.navbar-default .navbar-nav > .open > a,\n.navbar-default .navbar-nav > .open > a:hover,\n.navbar-default .navbar-nav > .open > a:focus {\n background-color: #e7e7e7;\n color: #555555;\n}\n@media (max-width: 767px) {\n .navbar-default .navbar-nav .open .dropdown-menu > li > a {\n color: #777777;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #333333;\n background-color: transparent;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #555555;\n background-color: #e7e7e7;\n }\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #cccccc;\n background-color: transparent;\n }\n}\n.navbar-default .navbar-link {\n color: #777777;\n}\n.navbar-default .navbar-link:hover {\n color: #333333;\n}\n.navbar-default .btn-link {\n color: #777777;\n}\n.navbar-default .btn-link:hover,\n.navbar-default .btn-link:focus {\n color: #333333;\n}\n.navbar-default .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-default .btn-link:hover,\n.navbar-default .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-default .btn-link:focus {\n color: #cccccc;\n}\n.navbar-inverse {\n background-color: #222222;\n border-color: #080808;\n}\n.navbar-inverse .navbar-brand {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-brand:hover,\n.navbar-inverse .navbar-brand:focus {\n color: #ffffff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-text {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-nav > li > a:hover,\n.navbar-inverse .navbar-nav > li > a:focus {\n color: #ffffff;\n background-color: transparent;\n}\n.navbar-inverse .navbar-nav > .active > a,\n.navbar-inverse .navbar-nav > .active > a:hover,\n.navbar-inverse .navbar-nav > .active > a:focus {\n color: #ffffff;\n background-color: #080808;\n}\n.navbar-inverse .navbar-nav > .disabled > a,\n.navbar-inverse .navbar-nav > .disabled > a:hover,\n.navbar-inverse .navbar-nav > .disabled > a:focus {\n color: #444444;\n background-color: transparent;\n}\n.navbar-inverse .navbar-toggle {\n border-color: #333333;\n}\n.navbar-inverse .navbar-toggle:hover,\n.navbar-inverse .navbar-toggle:focus {\n background-color: #333333;\n}\n.navbar-inverse .navbar-toggle .icon-bar {\n background-color: #ffffff;\n}\n.navbar-inverse .navbar-collapse,\n.navbar-inverse .navbar-form {\n border-color: #101010;\n}\n.navbar-inverse .navbar-nav > .open > a,\n.navbar-inverse .navbar-nav > .open > a:hover,\n.navbar-inverse .navbar-nav > .open > a:focus {\n background-color: #080808;\n color: #ffffff;\n}\n@media (max-width: 767px) {\n .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {\n border-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu .divider {\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {\n color: #9d9d9d;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {\n color: #ffffff;\n background-color: transparent;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {\n color: #ffffff;\n background-color: #080808;\n }\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,\n .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {\n color: #444444;\n background-color: transparent;\n }\n}\n.navbar-inverse .navbar-link {\n color: #9d9d9d;\n}\n.navbar-inverse .navbar-link:hover {\n color: #ffffff;\n}\n.navbar-inverse .btn-link {\n color: #9d9d9d;\n}\n.navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link:focus {\n color: #ffffff;\n}\n.navbar-inverse .btn-link[disabled]:hover,\nfieldset[disabled] .navbar-inverse .btn-link:hover,\n.navbar-inverse .btn-link[disabled]:focus,\nfieldset[disabled] .navbar-inverse .btn-link:focus {\n color: #444444;\n}\n.breadcrumb {\n padding: 8px 15px;\n margin-bottom: 20px;\n list-style: none;\n background-color: #f5f5f5;\n border-radius: 4px;\n}\n.breadcrumb > li {\n display: inline-block;\n}\n.breadcrumb > li + li:before {\n content: \"/\\00a0\";\n padding: 0 5px;\n color: #cccccc;\n}\n.breadcrumb > .active {\n color: #777777;\n}\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: 20px 0;\n border-radius: 4px;\n}\n.pagination > li {\n display: inline;\n}\n.pagination > li > a,\n.pagination > li > span {\n position: relative;\n float: left;\n padding: 6px 12px;\n line-height: 1.42857143;\n text-decoration: none;\n color: #337ab7;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n margin-left: -1px;\n}\n.pagination > li:first-child > a,\n.pagination > li:first-child > span {\n margin-left: 0;\n border-bottom-left-radius: 4px;\n border-top-left-radius: 4px;\n}\n.pagination > li:last-child > a,\n.pagination > li:last-child > span {\n border-bottom-right-radius: 4px;\n border-top-right-radius: 4px;\n}\n.pagination > li > a:hover,\n.pagination > li > span:hover,\n.pagination > li > a:focus,\n.pagination > li > span:focus {\n z-index: 3;\n color: #23527c;\n background-color: #eeeeee;\n border-color: #dddddd;\n}\n.pagination > .active > a,\n.pagination > .active > span,\n.pagination > .active > a:hover,\n.pagination > .active > span:hover,\n.pagination > .active > a:focus,\n.pagination > .active > span:focus {\n z-index: 2;\n color: #ffffff;\n background-color: #337ab7;\n border-color: #337ab7;\n cursor: default;\n}\n.pagination > .disabled > span,\n.pagination > .disabled > span:hover,\n.pagination > .disabled > span:focus,\n.pagination > .disabled > a,\n.pagination > .disabled > a:hover,\n.pagination > .disabled > a:focus {\n color: #777777;\n background-color: #ffffff;\n border-color: #dddddd;\n cursor: not-allowed;\n}\n.pagination-lg > li > a,\n.pagination-lg > li > span {\n padding: 10px 16px;\n font-size: 18px;\n line-height: 1.3333333;\n}\n.pagination-lg > li:first-child > a,\n.pagination-lg > li:first-child > span {\n border-bottom-left-radius: 6px;\n border-top-left-radius: 6px;\n}\n.pagination-lg > li:last-child > a,\n.pagination-lg > li:last-child > span {\n border-bottom-right-radius: 6px;\n border-top-right-radius: 6px;\n}\n.pagination-sm > li > a,\n.pagination-sm > li > span {\n padding: 5px 10px;\n font-size: 12px;\n line-height: 1.5;\n}\n.pagination-sm > li:first-child > a,\n.pagination-sm > li:first-child > span {\n border-bottom-left-radius: 3px;\n border-top-left-radius: 3px;\n}\n.pagination-sm > li:last-child > a,\n.pagination-sm > li:last-child > span {\n border-bottom-right-radius: 3px;\n border-top-right-radius: 3px;\n}\n.pager {\n padding-left: 0;\n margin: 20px 0;\n list-style: none;\n text-align: center;\n}\n.pager li {\n display: inline;\n}\n.pager li > a,\n.pager li > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 15px;\n}\n.pager li > a:hover,\n.pager li > a:focus {\n text-decoration: none;\n background-color: #eeeeee;\n}\n.pager .next > a,\n.pager .next > span {\n float: right;\n}\n.pager .previous > a,\n.pager .previous > span {\n float: left;\n}\n.pager .disabled > a,\n.pager .disabled > a:hover,\n.pager .disabled > a:focus,\n.pager .disabled > span {\n color: #777777;\n background-color: #ffffff;\n cursor: not-allowed;\n}\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: #ffffff;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n}\na.label:hover,\na.label:focus {\n color: #ffffff;\n text-decoration: none;\n cursor: pointer;\n}\n.label:empty {\n display: none;\n}\n.btn .label {\n position: relative;\n top: -1px;\n}\n.label-default {\n background-color: #777777;\n}\n.label-default[href]:hover,\n.label-default[href]:focus {\n background-color: #5e5e5e;\n}\n.label-primary {\n background-color: #337ab7;\n}\n.label-primary[href]:hover,\n.label-primary[href]:focus {\n background-color: #286090;\n}\n.label-success {\n background-color: #5cb85c;\n}\n.label-success[href]:hover,\n.label-success[href]:focus {\n background-color: #449d44;\n}\n.label-info {\n background-color: #5bc0de;\n}\n.label-info[href]:hover,\n.label-info[href]:focus {\n background-color: #31b0d5;\n}\n.label-warning {\n background-color: #f0ad4e;\n}\n.label-warning[href]:hover,\n.label-warning[href]:focus {\n background-color: #ec971f;\n}\n.label-danger {\n background-color: #d9534f;\n}\n.label-danger[href]:hover,\n.label-danger[href]:focus {\n background-color: #c9302c;\n}\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: 12px;\n font-weight: bold;\n color: #ffffff;\n line-height: 1;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: #777777;\n border-radius: 10px;\n}\n.badge:empty {\n display: none;\n}\n.btn .badge {\n position: relative;\n top: -1px;\n}\n.btn-xs .badge,\n.btn-group-xs > .btn .badge {\n top: 0;\n padding: 1px 5px;\n}\na.badge:hover,\na.badge:focus {\n color: #ffffff;\n text-decoration: none;\n cursor: pointer;\n}\n.list-group-item.active > .badge,\n.nav-pills > .active > a > .badge {\n color: #337ab7;\n background-color: #ffffff;\n}\n.list-group-item > .badge {\n float: right;\n}\n.list-group-item > .badge + .badge {\n margin-right: 5px;\n}\n.nav-pills > li > a > .badge {\n margin-left: 3px;\n}\n.jumbotron {\n padding-top: 30px;\n padding-bottom: 30px;\n margin-bottom: 30px;\n color: inherit;\n background-color: #eeeeee;\n}\n.jumbotron h1,\n.jumbotron .h1 {\n color: inherit;\n}\n.jumbotron p {\n margin-bottom: 15px;\n font-size: 21px;\n font-weight: 200;\n}\n.jumbotron > hr {\n border-top-color: #d5d5d5;\n}\n.container .jumbotron,\n.container-fluid .jumbotron {\n border-radius: 6px;\n}\n.jumbotron .container {\n max-width: 100%;\n}\n@media screen and (min-width: 768px) {\n .jumbotron {\n padding-top: 48px;\n padding-bottom: 48px;\n }\n .container .jumbotron,\n .container-fluid .jumbotron {\n padding-left: 60px;\n padding-right: 60px;\n }\n .jumbotron h1,\n .jumbotron .h1 {\n font-size: 63px;\n }\n}\n.thumbnail {\n display: block;\n padding: 4px;\n margin-bottom: 20px;\n line-height: 1.42857143;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n border-radius: 4px;\n -webkit-transition: border 0.2s ease-in-out;\n -o-transition: border 0.2s ease-in-out;\n transition: border 0.2s ease-in-out;\n}\n.thumbnail > img,\n.thumbnail a > img {\n margin-left: auto;\n margin-right: auto;\n}\na.thumbnail:hover,\na.thumbnail:focus,\na.thumbnail.active {\n border-color: #337ab7;\n}\n.thumbnail .caption {\n padding: 9px;\n color: #333333;\n}\n.alert {\n padding: 15px;\n margin-bottom: 20px;\n border: 1px solid transparent;\n border-radius: 4px;\n}\n.alert h4 {\n margin-top: 0;\n color: inherit;\n}\n.alert .alert-link {\n font-weight: bold;\n}\n.alert > p,\n.alert > ul {\n margin-bottom: 0;\n}\n.alert > p + p {\n margin-top: 5px;\n}\n.alert-dismissable,\n.alert-dismissible {\n padding-right: 35px;\n}\n.alert-dismissable .close,\n.alert-dismissible .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n}\n.alert-success {\n background-color: #dff0d8;\n border-color: #d6e9c6;\n color: #3c763d;\n}\n.alert-success hr {\n border-top-color: #c9e2b3;\n}\n.alert-success .alert-link {\n color: #2b542c;\n}\n.alert-info {\n background-color: #d9edf7;\n border-color: #bce8f1;\n color: #31708f;\n}\n.alert-info hr {\n border-top-color: #a6e1ec;\n}\n.alert-info .alert-link {\n color: #245269;\n}\n.alert-warning {\n background-color: #fcf8e3;\n border-color: #faebcc;\n color: #8a6d3b;\n}\n.alert-warning hr {\n border-top-color: #f7e1b5;\n}\n.alert-warning .alert-link {\n color: #66512c;\n}\n.alert-danger {\n background-color: #f2dede;\n border-color: #ebccd1;\n color: #a94442;\n}\n.alert-danger hr {\n border-top-color: #e4b9c0;\n}\n.alert-danger .alert-link {\n color: #843534;\n}\n@-webkit-keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n@keyframes progress-bar-stripes {\n from {\n background-position: 40px 0;\n }\n to {\n background-position: 0 0;\n }\n}\n.progress {\n overflow: hidden;\n height: 20px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n}\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: 12px;\n line-height: 20px;\n color: #ffffff;\n text-align: center;\n background-color: #337ab7;\n -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n -webkit-transition: width 0.6s ease;\n -o-transition: width 0.6s ease;\n transition: width 0.6s ease;\n}\n.progress-striped .progress-bar,\n.progress-bar-striped {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-size: 40px 40px;\n}\n.progress.active .progress-bar,\n.progress-bar.active {\n -webkit-animation: progress-bar-stripes 2s linear infinite;\n -o-animation: progress-bar-stripes 2s linear infinite;\n animation: progress-bar-stripes 2s linear infinite;\n}\n.progress-bar-success {\n background-color: #5cb85c;\n}\n.progress-striped .progress-bar-success {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-info {\n background-color: #5bc0de;\n}\n.progress-striped .progress-bar-info {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-warning {\n background-color: #f0ad4e;\n}\n.progress-striped .progress-bar-warning {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.progress-bar-danger {\n background-color: #d9534f;\n}\n.progress-striped .progress-bar-danger {\n background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);\n}\n.media {\n margin-top: 15px;\n}\n.media:first-child {\n margin-top: 0;\n}\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n.media-body {\n width: 10000px;\n}\n.media-object {\n display: block;\n}\n.media-object.img-thumbnail {\n max-width: none;\n}\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n.media-middle {\n vertical-align: middle;\n}\n.media-bottom {\n vertical-align: bottom;\n}\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n.list-group {\n margin-bottom: 20px;\n padding-left: 0;\n}\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n margin-bottom: -1px;\n background-color: #ffffff;\n border: 1px solid #dddddd;\n}\n.list-group-item:first-child {\n border-top-right-radius: 4px;\n border-top-left-radius: 4px;\n}\n.list-group-item:last-child {\n margin-bottom: 0;\n border-bottom-right-radius: 4px;\n border-bottom-left-radius: 4px;\n}\na.list-group-item,\nbutton.list-group-item {\n color: #555555;\n}\na.list-group-item .list-group-item-heading,\nbutton.list-group-item .list-group-item-heading {\n color: #333333;\n}\na.list-group-item:hover,\nbutton.list-group-item:hover,\na.list-group-item:focus,\nbutton.list-group-item:focus {\n text-decoration: none;\n color: #555555;\n background-color: #f5f5f5;\n}\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n.list-group-item.disabled,\n.list-group-item.disabled:hover,\n.list-group-item.disabled:focus {\n background-color: #eeeeee;\n color: #777777;\n cursor: not-allowed;\n}\n.list-group-item.disabled .list-group-item-heading,\n.list-group-item.disabled:hover .list-group-item-heading,\n.list-group-item.disabled:focus .list-group-item-heading {\n color: inherit;\n}\n.list-group-item.disabled .list-group-item-text,\n.list-group-item.disabled:hover .list-group-item-text,\n.list-group-item.disabled:focus .list-group-item-text {\n color: #777777;\n}\n.list-group-item.active,\n.list-group-item.active:hover,\n.list-group-item.active:focus {\n z-index: 2;\n color: #ffffff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.list-group-item.active .list-group-item-heading,\n.list-group-item.active:hover .list-group-item-heading,\n.list-group-item.active:focus .list-group-item-heading,\n.list-group-item.active .list-group-item-heading > small,\n.list-group-item.active:hover .list-group-item-heading > small,\n.list-group-item.active:focus .list-group-item-heading > small,\n.list-group-item.active .list-group-item-heading > .small,\n.list-group-item.active:hover .list-group-item-heading > .small,\n.list-group-item.active:focus .list-group-item-heading > .small {\n color: inherit;\n}\n.list-group-item.active .list-group-item-text,\n.list-group-item.active:hover .list-group-item-text,\n.list-group-item.active:focus .list-group-item-text {\n color: #c7ddef;\n}\n.list-group-item-success {\n color: #3c763d;\n background-color: #dff0d8;\n}\na.list-group-item-success,\nbutton.list-group-item-success {\n color: #3c763d;\n}\na.list-group-item-success .list-group-item-heading,\nbutton.list-group-item-success .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-success:hover,\nbutton.list-group-item-success:hover,\na.list-group-item-success:focus,\nbutton.list-group-item-success:focus {\n color: #3c763d;\n background-color: #d0e9c6;\n}\na.list-group-item-success.active,\nbutton.list-group-item-success.active,\na.list-group-item-success.active:hover,\nbutton.list-group-item-success.active:hover,\na.list-group-item-success.active:focus,\nbutton.list-group-item-success.active:focus {\n color: #fff;\n background-color: #3c763d;\n border-color: #3c763d;\n}\n.list-group-item-info {\n color: #31708f;\n background-color: #d9edf7;\n}\na.list-group-item-info,\nbutton.list-group-item-info {\n color: #31708f;\n}\na.list-group-item-info .list-group-item-heading,\nbutton.list-group-item-info .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-info:hover,\nbutton.list-group-item-info:hover,\na.list-group-item-info:focus,\nbutton.list-group-item-info:focus {\n color: #31708f;\n background-color: #c4e3f3;\n}\na.list-group-item-info.active,\nbutton.list-group-item-info.active,\na.list-group-item-info.active:hover,\nbutton.list-group-item-info.active:hover,\na.list-group-item-info.active:focus,\nbutton.list-group-item-info.active:focus {\n color: #fff;\n background-color: #31708f;\n border-color: #31708f;\n}\n.list-group-item-warning {\n color: #8a6d3b;\n background-color: #fcf8e3;\n}\na.list-group-item-warning,\nbutton.list-group-item-warning {\n color: #8a6d3b;\n}\na.list-group-item-warning .list-group-item-heading,\nbutton.list-group-item-warning .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-warning:hover,\nbutton.list-group-item-warning:hover,\na.list-group-item-warning:focus,\nbutton.list-group-item-warning:focus {\n color: #8a6d3b;\n background-color: #faf2cc;\n}\na.list-group-item-warning.active,\nbutton.list-group-item-warning.active,\na.list-group-item-warning.active:hover,\nbutton.list-group-item-warning.active:hover,\na.list-group-item-warning.active:focus,\nbutton.list-group-item-warning.active:focus {\n color: #fff;\n background-color: #8a6d3b;\n border-color: #8a6d3b;\n}\n.list-group-item-danger {\n color: #a94442;\n background-color: #f2dede;\n}\na.list-group-item-danger,\nbutton.list-group-item-danger {\n color: #a94442;\n}\na.list-group-item-danger .list-group-item-heading,\nbutton.list-group-item-danger .list-group-item-heading {\n color: inherit;\n}\na.list-group-item-danger:hover,\nbutton.list-group-item-danger:hover,\na.list-group-item-danger:focus,\nbutton.list-group-item-danger:focus {\n color: #a94442;\n background-color: #ebcccc;\n}\na.list-group-item-danger.active,\nbutton.list-group-item-danger.active,\na.list-group-item-danger.active:hover,\nbutton.list-group-item-danger.active:hover,\na.list-group-item-danger.active:focus,\nbutton.list-group-item-danger.active:focus {\n color: #fff;\n background-color: #a94442;\n border-color: #a94442;\n}\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n.panel {\n margin-bottom: 20px;\n background-color: #ffffff;\n border: 1px solid transparent;\n border-radius: 4px;\n -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.panel-body {\n padding: 15px;\n}\n.panel-heading {\n padding: 10px 15px;\n border-bottom: 1px solid transparent;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel-heading > .dropdown .dropdown-toggle {\n color: inherit;\n}\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: 16px;\n color: inherit;\n}\n.panel-title > a,\n.panel-title > small,\n.panel-title > .small,\n.panel-title > small > a,\n.panel-title > .small > a {\n color: inherit;\n}\n.panel-footer {\n padding: 10px 15px;\n background-color: #f5f5f5;\n border-top: 1px solid #dddddd;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .list-group,\n.panel > .panel-collapse > .list-group {\n margin-bottom: 0;\n}\n.panel > .list-group .list-group-item,\n.panel > .panel-collapse > .list-group .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n}\n.panel > .list-group:first-child .list-group-item:first-child,\n.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {\n border-top: 0;\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .list-group:last-child .list-group-item:last-child,\n.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {\n border-bottom: 0;\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .panel-heading + .panel-collapse > .list-group .list-group-item:first-child {\n border-top-right-radius: 0;\n border-top-left-radius: 0;\n}\n.panel-heading + .list-group .list-group-item:first-child {\n border-top-width: 0;\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n.panel > .table,\n.panel > .table-responsive > .table,\n.panel > .panel-collapse > .table {\n margin-bottom: 0;\n}\n.panel > .table caption,\n.panel > .table-responsive > .table caption,\n.panel > .panel-collapse > .table caption {\n padding-left: 15px;\n padding-right: 15px;\n}\n.panel > .table:first-child,\n.panel > .table-responsive:first-child > .table:first-child {\n border-top-right-radius: 3px;\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {\n border-top-left-radius: 3px;\n border-top-right-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {\n border-top-left-radius: 3px;\n}\n.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,\n.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,\n.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,\n.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {\n border-top-right-radius: 3px;\n}\n.panel > .table:last-child,\n.panel > .table-responsive:last-child > .table:last-child {\n border-bottom-right-radius: 3px;\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {\n border-bottom-left-radius: 3px;\n border-bottom-right-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {\n border-bottom-left-radius: 3px;\n}\n.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,\n.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,\n.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,\n.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {\n border-bottom-right-radius: 3px;\n}\n.panel > .panel-body + .table,\n.panel > .panel-body + .table-responsive,\n.panel > .table + .panel-body,\n.panel > .table-responsive + .panel-body {\n border-top: 1px solid #dddddd;\n}\n.panel > .table > tbody:first-child > tr:first-child th,\n.panel > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n}\n.panel > .table-bordered,\n.panel > .table-responsive > .table-bordered {\n border: 0;\n}\n.panel > .table-bordered > thead > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,\n.panel > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,\n.panel > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,\n.panel > .table-bordered > thead > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,\n.panel > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,\n.panel > .table-bordered > tfoot > tr > td:first-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {\n border-left: 0;\n}\n.panel > .table-bordered > thead > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,\n.panel > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,\n.panel > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,\n.panel > .table-bordered > thead > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,\n.panel > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,\n.panel > .table-bordered > tfoot > tr > td:last-child,\n.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {\n border-right: 0;\n}\n.panel > .table-bordered > thead > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,\n.panel > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,\n.panel > .table-bordered > thead > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,\n.panel > .table-bordered > tbody > tr:first-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {\n border-bottom: 0;\n}\n.panel > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,\n.panel > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,\n.panel > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,\n.panel > .table-bordered > tfoot > tr:last-child > th,\n.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {\n border-bottom: 0;\n}\n.panel > .table-responsive {\n border: 0;\n margin-bottom: 0;\n}\n.panel-group {\n margin-bottom: 20px;\n}\n.panel-group .panel {\n margin-bottom: 0;\n border-radius: 4px;\n}\n.panel-group .panel + .panel {\n margin-top: 5px;\n}\n.panel-group .panel-heading {\n border-bottom: 0;\n}\n.panel-group .panel-heading + .panel-collapse > .panel-body,\n.panel-group .panel-heading + .panel-collapse > .list-group {\n border-top: 1px solid #dddddd;\n}\n.panel-group .panel-footer {\n border-top: 0;\n}\n.panel-group .panel-footer + .panel-collapse .panel-body {\n border-bottom: 1px solid #dddddd;\n}\n.panel-default {\n border-color: #dddddd;\n}\n.panel-default > .panel-heading {\n color: #333333;\n background-color: #f5f5f5;\n border-color: #dddddd;\n}\n.panel-default > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #dddddd;\n}\n.panel-default > .panel-heading .badge {\n color: #f5f5f5;\n background-color: #333333;\n}\n.panel-default > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #dddddd;\n}\n.panel-primary {\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading {\n color: #ffffff;\n background-color: #337ab7;\n border-color: #337ab7;\n}\n.panel-primary > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #337ab7;\n}\n.panel-primary > .panel-heading .badge {\n color: #337ab7;\n background-color: #ffffff;\n}\n.panel-primary > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #337ab7;\n}\n.panel-success {\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading {\n color: #3c763d;\n background-color: #dff0d8;\n border-color: #d6e9c6;\n}\n.panel-success > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #d6e9c6;\n}\n.panel-success > .panel-heading .badge {\n color: #dff0d8;\n background-color: #3c763d;\n}\n.panel-success > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #d6e9c6;\n}\n.panel-info {\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading {\n color: #31708f;\n background-color: #d9edf7;\n border-color: #bce8f1;\n}\n.panel-info > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #bce8f1;\n}\n.panel-info > .panel-heading .badge {\n color: #d9edf7;\n background-color: #31708f;\n}\n.panel-info > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #bce8f1;\n}\n.panel-warning {\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading {\n color: #8a6d3b;\n background-color: #fcf8e3;\n border-color: #faebcc;\n}\n.panel-warning > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #faebcc;\n}\n.panel-warning > .panel-heading .badge {\n color: #fcf8e3;\n background-color: #8a6d3b;\n}\n.panel-warning > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #faebcc;\n}\n.panel-danger {\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading {\n color: #a94442;\n background-color: #f2dede;\n border-color: #ebccd1;\n}\n.panel-danger > .panel-heading + .panel-collapse > .panel-body {\n border-top-color: #ebccd1;\n}\n.panel-danger > .panel-heading .badge {\n color: #f2dede;\n background-color: #a94442;\n}\n.panel-danger > .panel-footer + .panel-collapse > .panel-body {\n border-bottom-color: #ebccd1;\n}\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n}\n.embed-responsive .embed-responsive-item,\n.embed-responsive iframe,\n.embed-responsive embed,\n.embed-responsive object,\n.embed-responsive video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n}\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: #f5f5f5;\n border: 1px solid #e3e3e3;\n border-radius: 4px;\n -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);\n}\n.well blockquote {\n border-color: #ddd;\n border-color: rgba(0, 0, 0, 0.15);\n}\n.well-lg {\n padding: 24px;\n border-radius: 6px;\n}\n.well-sm {\n padding: 9px;\n border-radius: 3px;\n}\n.close {\n float: right;\n font-size: 21px;\n font-weight: bold;\n line-height: 1;\n color: #000000;\n text-shadow: 0 1px 0 #ffffff;\n opacity: 0.2;\n filter: alpha(opacity=20);\n}\n.close:hover,\n.close:focus {\n color: #000000;\n text-decoration: none;\n cursor: pointer;\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\nbutton.close {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n}\n.modal-open {\n overflow: hidden;\n}\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1050;\n -webkit-overflow-scrolling: touch;\n outline: 0;\n}\n.modal.fade .modal-dialog {\n -webkit-transform: translate(0, -25%);\n -ms-transform: translate(0, -25%);\n -o-transform: translate(0, -25%);\n transform: translate(0, -25%);\n -webkit-transition: -webkit-transform 0.3s ease-out;\n -moz-transition: -moz-transform 0.3s ease-out;\n -o-transition: -o-transform 0.3s ease-out;\n transition: transform 0.3s ease-out;\n}\n.modal.in .modal-dialog {\n -webkit-transform: translate(0, 0);\n -ms-transform: translate(0, 0);\n -o-transform: translate(0, 0);\n transform: translate(0, 0);\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n.modal-content {\n position: relative;\n background-color: #ffffff;\n border: 1px solid #999999;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);\n background-clip: padding-box;\n outline: 0;\n}\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: 1040;\n background-color: #000000;\n}\n.modal-backdrop.fade {\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.modal-backdrop.in {\n opacity: 0.5;\n filter: alpha(opacity=50);\n}\n.modal-header {\n padding: 15px;\n border-bottom: 1px solid #e5e5e5;\n min-height: 16.42857143px;\n}\n.modal-header .close {\n margin-top: -2px;\n}\n.modal-title {\n margin: 0;\n line-height: 1.42857143;\n}\n.modal-body {\n position: relative;\n padding: 15px;\n}\n.modal-footer {\n padding: 15px;\n text-align: right;\n border-top: 1px solid #e5e5e5;\n}\n.modal-footer .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0;\n}\n.modal-footer .btn-group .btn + .btn {\n margin-left: -1px;\n}\n.modal-footer .btn-block + .btn-block {\n margin-left: 0;\n}\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n@media (min-width: 768px) {\n .modal-dialog {\n width: 600px;\n margin: 30px auto;\n }\n .modal-content {\n -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);\n }\n .modal-sm {\n width: 300px;\n }\n}\n@media (min-width: 992px) {\n .modal-lg {\n width: 900px;\n }\n}\n.tooltip {\n position: absolute;\n z-index: 1070;\n display: block;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 12px;\n opacity: 0;\n filter: alpha(opacity=0);\n}\n.tooltip.in {\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.tooltip.top {\n margin-top: -3px;\n padding: 5px 0;\n}\n.tooltip.right {\n margin-left: 3px;\n padding: 0 5px;\n}\n.tooltip.bottom {\n margin-top: 3px;\n padding: 5px 0;\n}\n.tooltip.left {\n margin-left: -3px;\n padding: 0 5px;\n}\n.tooltip-inner {\n max-width: 200px;\n padding: 3px 8px;\n color: #ffffff;\n text-align: center;\n background-color: #000000;\n border-radius: 4px;\n}\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.tooltip.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000000;\n}\n.tooltip.top-left .tooltip-arrow {\n bottom: 0;\n right: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000000;\n}\n.tooltip.top-right .tooltip-arrow {\n bottom: 0;\n left: 5px;\n margin-bottom: -5px;\n border-width: 5px 5px 0;\n border-top-color: #000000;\n}\n.tooltip.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -5px;\n border-width: 5px 5px 5px 0;\n border-right-color: #000000;\n}\n.tooltip.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -5px;\n border-width: 5px 0 5px 5px;\n border-left-color: #000000;\n}\n.tooltip.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000000;\n}\n.tooltip.bottom-left .tooltip-arrow {\n top: 0;\n right: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000000;\n}\n.tooltip.bottom-right .tooltip-arrow {\n top: 0;\n left: 5px;\n margin-top: -5px;\n border-width: 0 5px 5px;\n border-bottom-color: #000000;\n}\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: 1060;\n display: none;\n max-width: 276px;\n padding: 1px;\n font-family: \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: 1.42857143;\n text-align: left;\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n font-size: 14px;\n background-color: #ffffff;\n background-clip: padding-box;\n border: 1px solid #cccccc;\n border: 1px solid rgba(0, 0, 0, 0.2);\n border-radius: 6px;\n -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);\n}\n.popover.top {\n margin-top: -10px;\n}\n.popover.right {\n margin-left: 10px;\n}\n.popover.bottom {\n margin-top: 10px;\n}\n.popover.left {\n margin-left: -10px;\n}\n.popover-title {\n margin: 0;\n padding: 8px 14px;\n font-size: 14px;\n background-color: #f7f7f7;\n border-bottom: 1px solid #ebebeb;\n border-radius: 5px 5px 0 0;\n}\n.popover-content {\n padding: 9px 14px;\n}\n.popover > .arrow,\n.popover > .arrow:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n.popover > .arrow {\n border-width: 11px;\n}\n.popover > .arrow:after {\n border-width: 10px;\n content: \"\";\n}\n.popover.top > .arrow {\n left: 50%;\n margin-left: -11px;\n border-bottom-width: 0;\n border-top-color: #999999;\n border-top-color: rgba(0, 0, 0, 0.25);\n bottom: -11px;\n}\n.popover.top > .arrow:after {\n content: \" \";\n bottom: 1px;\n margin-left: -10px;\n border-bottom-width: 0;\n border-top-color: #ffffff;\n}\n.popover.right > .arrow {\n top: 50%;\n left: -11px;\n margin-top: -11px;\n border-left-width: 0;\n border-right-color: #999999;\n border-right-color: rgba(0, 0, 0, 0.25);\n}\n.popover.right > .arrow:after {\n content: \" \";\n left: 1px;\n bottom: -10px;\n border-left-width: 0;\n border-right-color: #ffffff;\n}\n.popover.bottom > .arrow {\n left: 50%;\n margin-left: -11px;\n border-top-width: 0;\n border-bottom-color: #999999;\n border-bottom-color: rgba(0, 0, 0, 0.25);\n top: -11px;\n}\n.popover.bottom > .arrow:after {\n content: \" \";\n top: 1px;\n margin-left: -10px;\n border-top-width: 0;\n border-bottom-color: #ffffff;\n}\n.popover.left > .arrow {\n top: 50%;\n right: -11px;\n margin-top: -11px;\n border-right-width: 0;\n border-left-color: #999999;\n border-left-color: rgba(0, 0, 0, 0.25);\n}\n.popover.left > .arrow:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: #ffffff;\n bottom: -10px;\n}\n.carousel {\n position: relative;\n}\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n}\n.carousel-inner > .item {\n display: none;\n position: relative;\n -webkit-transition: 0.6s ease-in-out left;\n -o-transition: 0.6s ease-in-out left;\n transition: 0.6s ease-in-out left;\n}\n.carousel-inner > .item > img,\n.carousel-inner > .item > a > img {\n line-height: 1;\n}\n@media all and (transform-3d), (-webkit-transform-3d) {\n .carousel-inner > .item {\n -webkit-transition: -webkit-transform 0.6s ease-in-out;\n -moz-transition: -moz-transform 0.6s ease-in-out;\n -o-transition: -o-transform 0.6s ease-in-out;\n transition: transform 0.6s ease-in-out;\n -webkit-backface-visibility: hidden;\n -moz-backface-visibility: hidden;\n backface-visibility: hidden;\n -webkit-perspective: 1000px;\n -moz-perspective: 1000px;\n perspective: 1000px;\n }\n .carousel-inner > .item.next,\n .carousel-inner > .item.active.right {\n -webkit-transform: translate3d(100%, 0, 0);\n transform: translate3d(100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.prev,\n .carousel-inner > .item.active.left {\n -webkit-transform: translate3d(-100%, 0, 0);\n transform: translate3d(-100%, 0, 0);\n left: 0;\n }\n .carousel-inner > .item.next.left,\n .carousel-inner > .item.prev.right,\n .carousel-inner > .item.active {\n -webkit-transform: translate3d(0, 0, 0);\n transform: translate3d(0, 0, 0);\n left: 0;\n }\n}\n.carousel-inner > .active,\n.carousel-inner > .next,\n.carousel-inner > .prev {\n display: block;\n}\n.carousel-inner > .active {\n left: 0;\n}\n.carousel-inner > .next,\n.carousel-inner > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n}\n.carousel-inner > .next {\n left: 100%;\n}\n.carousel-inner > .prev {\n left: -100%;\n}\n.carousel-inner > .next.left,\n.carousel-inner > .prev.right {\n left: 0;\n}\n.carousel-inner > .active.left {\n left: -100%;\n}\n.carousel-inner > .active.right {\n left: 100%;\n}\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: 15%;\n opacity: 0.5;\n filter: alpha(opacity=50);\n font-size: 20px;\n color: #ffffff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-control.left {\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);\n}\n.carousel-control.right {\n left: auto;\n right: 0;\n background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);\n background-repeat: repeat-x;\n filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);\n}\n.carousel-control:hover,\n.carousel-control:focus {\n outline: 0;\n color: #ffffff;\n text-decoration: none;\n opacity: 0.9;\n filter: alpha(opacity=90);\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-left,\n.carousel-control .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n}\n.carousel-control .icon-prev,\n.carousel-control .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n}\n.carousel-control .icon-next,\n.carousel-control .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n}\n.carousel-control .icon-prev,\n.carousel-control .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n}\n.carousel-control .icon-prev:before {\n content: '\\2039';\n}\n.carousel-control .icon-next:before {\n content: '\\203a';\n}\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n}\n.carousel-indicators li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid #ffffff;\n border-radius: 10px;\n cursor: pointer;\n background-color: #000 \\9;\n background-color: rgba(0, 0, 0, 0);\n}\n.carousel-indicators .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: #ffffff;\n}\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: #ffffff;\n text-align: center;\n text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);\n}\n.carousel-caption .btn {\n text-shadow: none;\n}\n@media screen and (min-width: 768px) {\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-prev,\n .carousel-control .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n font-size: 30px;\n }\n .carousel-control .glyphicon-chevron-left,\n .carousel-control .icon-prev {\n margin-left: -15px;\n }\n .carousel-control .glyphicon-chevron-right,\n .carousel-control .icon-next {\n margin-right: -15px;\n }\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n .carousel-indicators {\n bottom: 20px;\n }\n}\n.clearfix:before,\n.clearfix:after,\n.dl-horizontal dd:before,\n.dl-horizontal dd:after,\n.container:before,\n.container:after,\n.container-fluid:before,\n.container-fluid:after,\n.row:before,\n.row:after,\n.form-horizontal .form-group:before,\n.form-horizontal .form-group:after,\n.btn-toolbar:before,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:before,\n.btn-group-vertical > .btn-group:after,\n.nav:before,\n.nav:after,\n.navbar:before,\n.navbar:after,\n.navbar-header:before,\n.navbar-header:after,\n.navbar-collapse:before,\n.navbar-collapse:after,\n.pager:before,\n.pager:after,\n.panel-body:before,\n.panel-body:after,\n.modal-footer:before,\n.modal-footer:after {\n content: \" \";\n display: table;\n}\n.clearfix:after,\n.dl-horizontal dd:after,\n.container:after,\n.container-fluid:after,\n.row:after,\n.form-horizontal .form-group:after,\n.btn-toolbar:after,\n.btn-group-vertical > .btn-group:after,\n.nav:after,\n.navbar:after,\n.navbar-header:after,\n.navbar-collapse:after,\n.pager:after,\n.panel-body:after,\n.modal-footer:after {\n clear: both;\n}\n.center-block {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n font: 0/0 a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n.hidden {\n display: none !important;\n}\n.affix {\n position: fixed;\n}\n@-ms-viewport {\n width: device-width;\n}\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n display: none !important;\n}\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n@media (max-width: 767px) {\n .visible-xs {\n display: block !important;\n }\n table.visible-xs {\n display: table !important;\n }\n tr.visible-xs {\n display: table-row !important;\n }\n th.visible-xs,\n td.visible-xs {\n display: table-cell !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-block {\n display: block !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline {\n display: inline !important;\n }\n}\n@media (max-width: 767px) {\n .visible-xs-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm {\n display: block !important;\n }\n table.visible-sm {\n display: table !important;\n }\n tr.visible-sm {\n display: table-row !important;\n }\n th.visible-sm,\n td.visible-sm {\n display: table-cell !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-block {\n display: block !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline {\n display: inline !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .visible-sm-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md {\n display: block !important;\n }\n table.visible-md {\n display: table !important;\n }\n tr.visible-md {\n display: table-row !important;\n }\n th.visible-md,\n td.visible-md {\n display: table-cell !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-block {\n display: block !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline {\n display: inline !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .visible-md-inline-block {\n display: inline-block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg {\n display: block !important;\n }\n table.visible-lg {\n display: table !important;\n }\n tr.visible-lg {\n display: table-row !important;\n }\n th.visible-lg,\n td.visible-lg {\n display: table-cell !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-block {\n display: block !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline {\n display: inline !important;\n }\n}\n@media (min-width: 1200px) {\n .visible-lg-inline-block {\n display: inline-block !important;\n }\n}\n@media (max-width: 767px) {\n .hidden-xs {\n display: none !important;\n }\n}\n@media (min-width: 768px) and (max-width: 991px) {\n .hidden-sm {\n display: none !important;\n }\n}\n@media (min-width: 992px) and (max-width: 1199px) {\n .hidden-md {\n display: none !important;\n }\n}\n@media (min-width: 1200px) {\n .hidden-lg {\n display: none !important;\n }\n}\n.visible-print {\n display: none !important;\n}\n@media print {\n .visible-print {\n display: block !important;\n }\n table.visible-print {\n display: table !important;\n }\n tr.visible-print {\n display: table-row !important;\n }\n th.visible-print,\n td.visible-print {\n display: table-cell !important;\n }\n}\n.visible-print-block {\n display: none !important;\n}\n@media print {\n .visible-print-block {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n}\n@media print {\n .visible-print-inline {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n}\n@media print {\n .visible-print-inline-block {\n display: inline-block !important;\n }\n}\n@media print {\n .hidden-print {\n display: none !important;\n }\n}\n/*# sourceMappingURL=bootstrap.css.map */","/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */\n\n//\n// 1. Set default font family to sans-serif.\n// 2. Prevent iOS and IE text size adjust after device orientation change,\n// without disabling user zoom.\n//\n\nhtml {\n font-family: sans-serif; // 1\n -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\n}\n\n// HTML5 display definitions\n// ==========================================================================\n\n//\n// Correct `block` display not defined for any HTML5 element in IE 8/9.\n// Correct `block` display not defined for `details` or `summary` in IE 10/11\n// and Firefox.\n// Correct `block` display not defined for `main` in IE 11.\n//\n\narticle,\naside,\ndetails,\nfigcaption,\nfigure,\nfooter,\nheader,\nhgroup,\nmain,\nmenu,\nnav,\nsection,\nsummary {\n display: block;\n}\n\n//\n// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\n}\n\n//\n// Prevent modern browsers from displaying `audio` without controls.\n// Remove excess height in iOS 5 devices.\n//\n\naudio:not([controls]) {\n display: none;\n height: 0;\n}\n\n//\n// Address `[hidden]` styling not present in IE 8/9/10.\n// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background-color: transparent;\n}\n\n//\n// Improve readability of focused elements when they are also in an\n// active/hover state.\n//\n\na:active,\na:hover {\n outline: 0;\n}\n\n// Text-level semantics\n// ==========================================================================\n\n//\n// Address styling not present in IE 8/9/10/11, Safari, and Chrome.\n//\n\nabbr[title] {\n border-bottom: 1px dotted;\n}\n\n//\n// Address style set to `bolder` in Firefox 4+, Safari, and Chrome.\n//\n\nb,\nstrong {\n font-weight: bold;\n}\n\n//\n// Address styling not present in Safari and Chrome.\n//\n\ndfn {\n font-style: italic;\n}\n\n//\n// Address variable `h1` font-size and margin within `section` and `article`\n// contexts in Firefox 4+, Safari, and Chrome.\n//\n\nh1 {\n font-size: 2em;\n margin: 0.67em 0;\n}\n\n//\n// Address styling not present in IE 8/9.\n//\n\nmark {\n background: #ff0;\n color: #000;\n}\n\n//\n// Address inconsistent and variable font size in all browsers.\n//\n\nsmall {\n font-size: 80%;\n}\n\n//\n// Prevent `sub` and `sup` affecting `line-height` in all browsers.\n//\n\nsub,\nsup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n}\n\nsup {\n top: -0.5em;\n}\n\nsub {\n bottom: -0.25em;\n}\n\n// Embedded content\n// ==========================================================================\n\n//\n// Remove border when inside `a` element in IE 8/9/10.\n//\n\nimg {\n border: 0;\n}\n\n//\n// Correct overflow not hidden in IE 9/10/11.\n//\n\nsvg:not(:root) {\n overflow: hidden;\n}\n\n// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari.\n//\n\nfigure {\n margin: 1em 40px;\n}\n\n//\n// Address differences between Firefox and other browsers.\n//\n\nhr {\n box-sizing: content-box;\n height: 0;\n}\n\n//\n// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10/11.\n//\n\nbutton {\n overflow: visible;\n}\n\n//\n// Address inconsistent `text-transform` inheritance for `button` and `select`.\n// All other form control elements do not inherit `text-transform` values.\n// Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.\n// Correct `select` style inheritance in Firefox.\n//\n\nbutton,\nselect {\n text-transform: none;\n}\n\n//\n// 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`\n// and `video` controls.\n// 2. Correct inability to style clickable `input` types in iOS.\n// 3. Improve usability and consistency of cursor style between image-type\n// `input` and others.\n//\n\nbutton,\nhtml input[type=\"button\"], // 1\ninput[type=\"reset\"],\ninput[type=\"submit\"] {\n -webkit-appearance: button; // 2\n cursor: pointer; // 3\n}\n\n//\n// Re-set default cursor for disabled elements.\n//\n\nbutton[disabled],\nhtml input[disabled] {\n cursor: default;\n}\n\n//\n// Remove inner padding and border in Firefox 4+.\n//\n\nbutton::-moz-focus-inner,\ninput::-moz-focus-inner {\n border: 0;\n padding: 0;\n}\n\n//\n// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\n}\n\n//\n// 1. Address `appearance` set to `searchfield` in Safari and Chrome.\n// 2. Address `box-sizing` set to `border-box` in Safari and Chrome.\n//\n\ninput[type=\"search\"] {\n -webkit-appearance: textfield; // 1\n box-sizing: content-box; //2\n}\n\n//\n// Remove inner padding and search cancel button in Safari and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\n}\n\n//\n// Define consistent border, margin, and padding.\n//\n\nfieldset {\n border: 1px solid #c0c0c0;\n margin: 0 2px;\n padding: 0.35em 0.625em 0.75em;\n}\n\n//\n// 1. Correct `color` not being inherited in IE 8/9/10/11.\n// 2. Remove padding so people aren't caught out if they zero out fieldsets.\n//\n\nlegend {\n border: 0; // 1\n padding: 0; // 2\n}\n\n//\n// Remove default vertical scrollbar in IE 8/9/10/11.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\n}\n\n// Tables\n// ==========================================================================\n\n//\n// Remove most spacing between table cells.\n//\n\ntable {\n border-collapse: collapse;\n border-spacing: 0;\n}\n\ntd,\nth {\n padding: 0;\n}\n","/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */\n\n// ==========================================================================\n// Print styles.\n// Inlined to avoid the additional HTTP request: h5bp.com/r\n// ==========================================================================\n\n@media print {\n *,\n *:before,\n *:after {\n background: transparent !important;\n color: #000 !important; // Black prints faster: h5bp.com/s\n box-shadow: none !important;\n text-shadow: none !important;\n }\n\n a,\n a:visited {\n text-decoration: underline;\n }\n\n a[href]:after {\n content: \" (\" attr(href) \")\";\n }\n\n abbr[title]:after {\n content: \" (\" attr(title) \")\";\n }\n\n // Don't show links that are fragment identifiers,\n // or use the `javascript:` pseudo protocol\n a[href^=\"#\"]:after,\n a[href^=\"javascript:\"]:after {\n content: \"\";\n }\n\n pre,\n blockquote {\n border: 1px solid #999;\n page-break-inside: avoid;\n }\n\n thead {\n display: table-header-group; // h5bp.com/t\n }\n\n tr,\n img {\n page-break-inside: avoid;\n }\n\n img {\n max-width: 100% !important;\n }\n\n p,\n h2,\n h3 {\n orphans: 3;\n widows: 3;\n }\n\n h2,\n h3 {\n page-break-after: avoid;\n }\n\n // Bootstrap specific changes start\n\n // Bootstrap components\n .navbar {\n display: none;\n }\n .btn,\n .dropup > .btn {\n > .caret {\n border-top-color: #000 !important;\n }\n }\n .label {\n border: 1px solid #000;\n }\n\n .table {\n border-collapse: collapse !important;\n\n td,\n th {\n background-color: #fff !important;\n }\n }\n .table-bordered {\n th,\n td {\n border: 1px solid #ddd !important;\n }\n }\n\n // Bootstrap specific changes end\n}\n","//\n// Glyphicons for Bootstrap\n//\n// Since icons are fonts, they can be placed anywhere text is placed and are\n// thus automatically sized to match the surrounding child. To use, create an\n// inline element with the appropriate classes, like so:\n//\n// <a href=\"#\"><span class=\"glyphicon glyphicon-star\"></span> Star</a>\n\n// Import the fonts\n@font-face {\n font-family: 'Glyphicons Halflings';\n src: url('@{icon-font-path}@{icon-font-name}.eot');\n src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'),\n url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'),\n url('@{icon-font-path}@{icon-font-name}.woff') format('woff'),\n url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'),\n url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg');\n}\n\n// Catchall baseclass\n.glyphicon {\n position: relative;\n top: 1px;\n display: inline-block;\n font-family: 'Glyphicons Halflings';\n font-style: normal;\n font-weight: normal;\n line-height: 1;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n}\n\n// Individual icons\n.glyphicon-asterisk { &:before { content: \"\\2a\"; } }\n.glyphicon-plus { &:before { content: \"\\2b\"; } }\n.glyphicon-euro,\n.glyphicon-eur { &:before { content: \"\\20ac\"; } }\n.glyphicon-minus { &:before { content: \"\\2212\"; } }\n.glyphicon-cloud { &:before { content: \"\\2601\"; } }\n.glyphicon-envelope { &:before { content: \"\\2709\"; } }\n.glyphicon-pencil { &:before { content: \"\\270f\"; } }\n.glyphicon-glass { &:before { content: \"\\e001\"; } }\n.glyphicon-music { &:before { content: \"\\e002\"; } }\n.glyphicon-search { &:before { content: \"\\e003\"; } }\n.glyphicon-heart { &:before { content: \"\\e005\"; } }\n.glyphicon-star { &:before { content: \"\\e006\"; } }\n.glyphicon-star-empty { &:before { content: \"\\e007\"; } }\n.glyphicon-user { &:before { content: \"\\e008\"; } }\n.glyphicon-film { &:before { content: \"\\e009\"; } }\n.glyphicon-th-large { &:before { content: \"\\e010\"; } }\n.glyphicon-th { &:before { content: \"\\e011\"; } }\n.glyphicon-th-list { &:before { content: \"\\e012\"; } }\n.glyphicon-ok { &:before { content: \"\\e013\"; } }\n.glyphicon-remove { &:before { content: \"\\e014\"; } }\n.glyphicon-zoom-in { &:before { content: \"\\e015\"; } }\n.glyphicon-zoom-out { &:before { content: \"\\e016\"; } }\n.glyphicon-off { &:before { content: \"\\e017\"; } }\n.glyphicon-signal { &:before { content: \"\\e018\"; } }\n.glyphicon-cog { &:before { content: \"\\e019\"; } }\n.glyphicon-trash { &:before { content: \"\\e020\"; } }\n.glyphicon-home { &:before { content: \"\\e021\"; } }\n.glyphicon-file { &:before { content: \"\\e022\"; } }\n.glyphicon-time { &:before { content: \"\\e023\"; } }\n.glyphicon-road { &:before { content: \"\\e024\"; } }\n.glyphicon-download-alt { &:before { content: \"\\e025\"; } }\n.glyphicon-download { &:before { content: \"\\e026\"; } }\n.glyphicon-upload { &:before { content: \"\\e027\"; } }\n.glyphicon-inbox { &:before { content: \"\\e028\"; } }\n.glyphicon-play-circle { &:before { content: \"\\e029\"; } }\n.glyphicon-repeat { &:before { content: \"\\e030\"; } }\n.glyphicon-refresh { &:before { content: \"\\e031\"; } }\n.glyphicon-list-alt { &:before { content: \"\\e032\"; } }\n.glyphicon-lock { &:before { content: \"\\e033\"; } }\n.glyphicon-flag { &:before { content: \"\\e034\"; } }\n.glyphicon-headphones { &:before { content: \"\\e035\"; } }\n.glyphicon-volume-off { &:before { content: \"\\e036\"; } }\n.glyphicon-volume-down { &:before { content: \"\\e037\"; } }\n.glyphicon-volume-up { &:before { content: \"\\e038\"; } }\n.glyphicon-qrcode { &:before { content: \"\\e039\"; } }\n.glyphicon-barcode { &:before { content: \"\\e040\"; } }\n.glyphicon-tag { &:before { content: \"\\e041\"; } }\n.glyphicon-tags { &:before { content: \"\\e042\"; } }\n.glyphicon-book { &:before { content: \"\\e043\"; } }\n.glyphicon-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\n.glyphicon-font { &:before { content: \"\\e047\"; } }\n.glyphicon-bold { &:before { content: \"\\e048\"; } }\n.glyphicon-italic { &:before { content: \"\\e049\"; } }\n.glyphicon-text-height { &:before { content: \"\\e050\"; } }\n.glyphicon-text-width { &:before { content: \"\\e051\"; } }\n.glyphicon-align-left { &:before { content: \"\\e052\"; } }\n.glyphicon-align-center { &:before { content: \"\\e053\"; } }\n.glyphicon-align-right { &:before { content: \"\\e054\"; } }\n.glyphicon-align-justify { &:before { content: \"\\e055\"; } }\n.glyphicon-list { &:before { content: \"\\e056\"; } }\n.glyphicon-indent-left { &:before { content: \"\\e057\"; } }\n.glyphicon-indent-right { &:before { content: \"\\e058\"; } }\n.glyphicon-facetime-video { &:before { content: \"\\e059\"; } }\n.glyphicon-picture { &:before { content: \"\\e060\"; } }\n.glyphicon-map-marker { &:before { content: \"\\e062\"; } }\n.glyphicon-adjust { &:before { content: \"\\e063\"; } }\n.glyphicon-tint { &:before { content: \"\\e064\"; } }\n.glyphicon-edit { &:before { content: \"\\e065\"; } }\n.glyphicon-share { &:before { content: \"\\e066\"; } }\n.glyphicon-check { &:before { content: \"\\e067\"; } }\n.glyphicon-move { &:before { content: \"\\e068\"; } }\n.glyphicon-step-backward { &:before { content: \"\\e069\"; } }\n.glyphicon-fast-backward { &:before { content: \"\\e070\"; } }\n.glyphicon-backward { &:before { content: \"\\e071\"; } }\n.glyphicon-play { &:before { content: \"\\e072\"; } }\n.glyphicon-pause { &:before { content: \"\\e073\"; } }\n.glyphicon-stop { &:before { content: \"\\e074\"; } }\n.glyphicon-forward { &:before { content: \"\\e075\"; } }\n.glyphicon-fast-forward { &:before { content: \"\\e076\"; } }\n.glyphicon-step-forward { &:before { content: \"\\e077\"; } }\n.glyphicon-eject { &:before { content: \"\\e078\"; } }\n.glyphicon-chevron-left { &:before { content: \"\\e079\"; } }\n.glyphicon-chevron-right { &:before { content: \"\\e080\"; } }\n.glyphicon-plus-sign { &:before { content: \"\\e081\"; } }\n.glyphicon-minus-sign { &:before { content: \"\\e082\"; } }\n.glyphicon-remove-sign { &:before { content: \"\\e083\"; } }\n.glyphicon-ok-sign { &:before { content: \"\\e084\"; } }\n.glyphicon-question-sign { &:before { content: \"\\e085\"; } }\n.glyphicon-info-sign { &:before { content: \"\\e086\"; } }\n.glyphicon-screenshot { &:before { content: \"\\e087\"; } }\n.glyphicon-remove-circle { &:before { content: \"\\e088\"; } }\n.glyphicon-ok-circle { &:before { content: \"\\e089\"; } }\n.glyphicon-ban-circle { &:before { content: \"\\e090\"; } }\n.glyphicon-arrow-left { &:before { content: \"\\e091\"; } }\n.glyphicon-arrow-right { &:before { content: \"\\e092\"; } }\n.glyphicon-arrow-up { &:before { content: \"\\e093\"; } }\n.glyphicon-arrow-down { &:before { content: \"\\e094\"; } }\n.glyphicon-share-alt { &:before { content: \"\\e095\"; } }\n.glyphicon-resize-full { &:before { content: \"\\e096\"; } }\n.glyphicon-resize-small { &:before { content: \"\\e097\"; } }\n.glyphicon-exclamation-sign { &:before { content: \"\\e101\"; } }\n.glyphicon-gift { &:before { content: \"\\e102\"; } }\n.glyphicon-leaf { &:before { content: \"\\e103\"; } }\n.glyphicon-fire { &:before { content: \"\\e104\"; } }\n.glyphicon-eye-open { &:before { content: \"\\e105\"; } }\n.glyphicon-eye-close { &:before { content: \"\\e106\"; } }\n.glyphicon-warning-sign { &:before { content: \"\\e107\"; } }\n.glyphicon-plane { &:before { content: \"\\e108\"; } }\n.glyphicon-calendar { &:before { content: \"\\e109\"; } }\n.glyphicon-random { &:before { content: \"\\e110\"; } }\n.glyphicon-comment { &:before { content: \"\\e111\"; } }\n.glyphicon-magnet { &:before { content: \"\\e112\"; } }\n.glyphicon-chevron-up { &:before { content: \"\\e113\"; } }\n.glyphicon-chevron-down { &:before { content: \"\\e114\"; } }\n.glyphicon-retweet { &:before { content: \"\\e115\"; } }\n.glyphicon-shopping-cart { &:before { content: \"\\e116\"; } }\n.glyphicon-folder-close { &:before { content: \"\\e117\"; } }\n.glyphicon-folder-open { &:before { content: \"\\e118\"; } }\n.glyphicon-resize-vertical { &:before { content: \"\\e119\"; } }\n.glyphicon-resize-horizontal { &:before { content: \"\\e120\"; } }\n.glyphicon-hdd { &:before { content: \"\\e121\"; } }\n.glyphicon-bullhorn { &:before { content: \"\\e122\"; } }\n.glyphicon-bell { &:before { content: \"\\e123\"; } }\n.glyphicon-certificate { &:before { content: \"\\e124\"; } }\n.glyphicon-thumbs-up { &:before { content: \"\\e125\"; } }\n.glyphicon-thumbs-down { &:before { content: \"\\e126\"; } }\n.glyphicon-hand-right { &:before { content: \"\\e127\"; } }\n.glyphicon-hand-left { &:before { content: \"\\e128\"; } }\n.glyphicon-hand-up { &:before { content: \"\\e129\"; } }\n.glyphicon-hand-down { &:before { content: \"\\e130\"; } }\n.glyphicon-circle-arrow-right { &:before { content: \"\\e131\"; } }\n.glyphicon-circle-arrow-left { &:before { content: \"\\e132\"; } }\n.glyphicon-circle-arrow-up { &:before { content: \"\\e133\"; } }\n.glyphicon-circle-arrow-down { &:before { content: \"\\e134\"; } }\n.glyphicon-globe { &:before { content: \"\\e135\"; } }\n.glyphicon-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\n.glyphicon-usd { &:before { content: \"\\e148\"; } }\n.glyphicon-gbp { &:before { content: \"\\e149\"; } }\n.glyphicon-sort { &:before { content: \"\\e150\"; } }\n.glyphicon-sort-by-alphabet { &:before { content: \"\\e151\"; } }\n.glyphicon-sort-by-alphabet-alt { &:before { content: \"\\e152\"; } }\n.glyphicon-sort-by-order { &:before { content: \"\\e153\"; } }\n.glyphicon-sort-by-order-alt { &:before { content: \"\\e154\"; } }\n.glyphicon-sort-by-attributes { &:before { content: \"\\e155\"; } }\n.glyphicon-sort-by-attributes-alt { &:before { content: \"\\e156\"; } }\n.glyphicon-unchecked { &:before { content: \"\\e157\"; } }\n.glyphicon-expand { &:before { content: \"\\e158\"; } }\n.glyphicon-collapse-down { &:before { content: \"\\e159\"; } }\n.glyphicon-collapse-up { &:before { content: \"\\e160\"; } }\n.glyphicon-log-in { &:before { content: \"\\e161\"; } }\n.glyphicon-flash { &:before { content: \"\\e162\"; } }\n.glyphicon-log-out { &:before { content: \"\\e163\"; } }\n.glyphicon-new-window { &:before { content: \"\\e164\"; } }\n.glyphicon-record { &:before { content: \"\\e165\"; } }\n.glyphicon-save { &:before { content: \"\\e166\"; } }\n.glyphicon-open { &:before { content: \"\\e167\"; } }\n.glyphicon-saved { &:before { content: \"\\e168\"; } }\n.glyphicon-import { &:before { content: \"\\e169\"; } }\n.glyphicon-export { &:before { content: \"\\e170\"; } }\n.glyphicon-send { &:before { content: \"\\e171\"; } }\n.glyphicon-floppy-disk { &:before { content: \"\\e172\"; } }\n.glyphicon-floppy-saved { &:before { content: \"\\e173\"; } }\n.glyphicon-floppy-remove { &:before { content: \"\\e174\"; } }\n.glyphicon-floppy-save { &:before { content: \"\\e175\"; } }\n.glyphicon-floppy-open { &:before { content: \"\\e176\"; } }\n.glyphicon-credit-card { &:before { content: \"\\e177\"; } }\n.glyphicon-transfer { &:before { content: \"\\e178\"; } }\n.glyphicon-cutlery { &:before { content: \"\\e179\"; } }\n.glyphicon-header { &:before { content: \"\\e180\"; } }\n.glyphicon-compressed { &:before { content: \"\\e181\"; } }\n.glyphicon-earphone { &:before { content: \"\\e182\"; } }\n.glyphicon-phone-alt { &:before { content: \"\\e183\"; } }\n.glyphicon-tower { &:before { content: \"\\e184\"; } }\n.glyphicon-stats { &:before { content: \"\\e185\"; } }\n.glyphicon-sd-video { &:before { content: \"\\e186\"; } }\n.glyphicon-hd-video { &:before { content: \"\\e187\"; } }\n.glyphicon-subtitles { &:before { content: \"\\e188\"; } }\n.glyphicon-sound-stereo { &:before { content: \"\\e189\"; } }\n.glyphicon-sound-dolby { &:before { content: \"\\e190\"; } }\n.glyphicon-sound-5-1 { &:before { content: \"\\e191\"; } }\n.glyphicon-sound-6-1 { &:before { content: \"\\e192\"; } }\n.glyphicon-sound-7-1 { &:before { content: \"\\e193\"; } }\n.glyphicon-copyright-mark { &:before { content: \"\\e194\"; } }\n.glyphicon-registration-mark { &:before { content: \"\\e195\"; } }\n.glyphicon-cloud-download { &:before { content: \"\\e197\"; } }\n.glyphicon-cloud-upload { &:before { content: \"\\e198\"; } }\n.glyphicon-tree-conifer { &:before { content: \"\\e199\"; } }\n.glyphicon-tree-deciduous { &:before { content: \"\\e200\"; } }\n.glyphicon-cd { &:before { content: \"\\e201\"; } }\n.glyphicon-save-file { &:before { content: \"\\e202\"; } }\n.glyphicon-open-file { &:before { content: \"\\e203\"; } }\n.glyphicon-level-up { &:before { content: \"\\e204\"; } }\n.glyphicon-copy { &:before { content: \"\\e205\"; } }\n.glyphicon-paste { &:before { content: \"\\e206\"; } }\n// The following 2 Glyphicons are omitted for the time being because\n// they currently use Unicode codepoints that are outside the\n// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle\n// non-BMP codepoints in CSS string escapes, and thus can't display these two icons.\n// Notably, the bug affects some older versions of the Android Browser.\n// More info: https://github.com/twbs/bootstrap/issues/10106\n// .glyphicon-door { &:before { content: \"\\1f6aa\"; } }\n// .glyphicon-key { &:before { content: \"\\1f511\"; } }\n.glyphicon-alert { &:before { content: \"\\e209\"; } }\n.glyphicon-equalizer { &:before { content: \"\\e210\"; } }\n.glyphicon-king { &:before { content: \"\\e211\"; } }\n.glyphicon-queen { &:before { content: \"\\e212\"; } }\n.glyphicon-pawn { &:before { content: \"\\e213\"; } }\n.glyphicon-bishop { &:before { content: \"\\e214\"; } }\n.glyphicon-knight { &:before { content: \"\\e215\"; } }\n.glyphicon-baby-formula { &:before { content: \"\\e216\"; } }\n.glyphicon-tent { &:before { content: \"\\26fa\"; } }\n.glyphicon-blackboard { &:before { content: \"\\e218\"; } }\n.glyphicon-bed { &:before { content: \"\\e219\"; } }\n.glyphicon-apple { &:before { content: \"\\f8ff\"; } }\n.glyphicon-erase { &:before { content: \"\\e221\"; } }\n.glyphicon-hourglass { &:before { content: \"\\231b\"; } }\n.glyphicon-lamp { &:before { content: \"\\e223\"; } }\n.glyphicon-duplicate { &:before { content: \"\\e224\"; } }\n.glyphicon-piggy-bank { &:before { content: \"\\e225\"; } }\n.glyphicon-scissors { &:before { content: \"\\e226\"; } }\n.glyphicon-bitcoin { &:before { content: \"\\e227\"; } }\n.glyphicon-btc { &:before { content: \"\\e227\"; } }\n.glyphicon-xbt { &:before { content: \"\\e227\"; } }\n.glyphicon-yen { &:before { content: \"\\00a5\"; } }\n.glyphicon-jpy { &:before { content: \"\\00a5\"; } }\n.glyphicon-ruble { &:before { content: \"\\20bd\"; } }\n.glyphicon-rub { &:before { content: \"\\20bd\"; } }\n.glyphicon-scale { &:before { content: \"\\e230\"; } }\n.glyphicon-ice-lolly { &:before { content: \"\\e231\"; } }\n.glyphicon-ice-lolly-tasted { &:before { content: \"\\e232\"; } }\n.glyphicon-education { &:before { content: \"\\e233\"; } }\n.glyphicon-option-horizontal { &:before { content: \"\\e234\"; } }\n.glyphicon-option-vertical { &:before { content: \"\\e235\"; } }\n.glyphicon-menu-hamburger { &:before { content: \"\\e236\"; } }\n.glyphicon-modal-window { &:before { content: \"\\e237\"; } }\n.glyphicon-oil { &:before { content: \"\\e238\"; } }\n.glyphicon-grain { &:before { content: \"\\e239\"; } }\n.glyphicon-sunglasses { &:before { content: \"\\e240\"; } }\n.glyphicon-text-size { &:before { content: \"\\e241\"; } }\n.glyphicon-text-color { &:before { content: \"\\e242\"; } }\n.glyphicon-text-background { &:before { content: \"\\e243\"; } }\n.glyphicon-object-align-top { &:before { content: \"\\e244\"; } }\n.glyphicon-object-align-bottom { &:before { content: \"\\e245\"; } }\n.glyphicon-object-align-horizontal{ &:before { content: \"\\e246\"; } }\n.glyphicon-object-align-left { &:before { content: \"\\e247\"; } }\n.glyphicon-object-align-vertical { &:before { content: \"\\e248\"; } }\n.glyphicon-object-align-right { &:before { content: \"\\e249\"; } }\n.glyphicon-triangle-right { &:before { content: \"\\e250\"; } }\n.glyphicon-triangle-left { &:before { content: \"\\e251\"; } }\n.glyphicon-triangle-bottom { &:before { content: \"\\e252\"; } }\n.glyphicon-triangle-top { &:before { content: \"\\e253\"; } }\n.glyphicon-console { &:before { content: \"\\e254\"; } }\n.glyphicon-superscript { &:before { content: \"\\e255\"; } }\n.glyphicon-subscript { &:before { content: \"\\e256\"; } }\n.glyphicon-menu-left { &:before { content: \"\\e257\"; } }\n.glyphicon-menu-right { &:before { content: \"\\e258\"; } }\n.glyphicon-menu-down { &:before { content: \"\\e259\"; } }\n.glyphicon-menu-up { &:before { content: \"\\e260\"; } }\n","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\n}\n*:before,\n*:after {\n .box-sizing(border-box);\n}\n\n\n// Body reset\n\nhtml {\n font-size: 10px;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n\nbody {\n font-family: @font-family-base;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @text-color;\n background-color: @body-bg;\n}\n\n// Reset fonts for relevant elements\ninput,\nbutton,\nselect,\ntextarea {\n font-family: inherit;\n font-size: inherit;\n line-height: inherit;\n}\n\n\n// Links\n\na {\n color: @link-color;\n text-decoration: none;\n\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n }\n\n &:focus {\n .tab-focus();\n }\n}\n\n\n// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\n}\n\n\n// Images\n\nimg {\n vertical-align: middle;\n}\n\n// Responsive images (ensure images don't scale beyond their parents)\n.img-responsive {\n .img-responsive();\n}\n\n// Rounded corners\n.img-rounded {\n border-radius: @border-radius-large;\n}\n\n// Image thumbnails\n//\n// Heads up! This is mixin-ed into thumbnails.less for `.thumbnail`.\n.img-thumbnail {\n padding: @thumbnail-padding;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(all .2s ease-in-out);\n\n // Keep them at most 100% wide\n .img-responsive(inline-block);\n}\n\n// Perfect circle\n.img-circle {\n border-radius: 50%; // set radius in percents\n}\n\n\n// Horizontal rules\n\nhr {\n margin-top: @line-height-computed;\n margin-bottom: @line-height-computed;\n border: 0;\n border-top: 1px solid @hr-border;\n}\n\n\n// Only display content to screen readers\n//\n// See: http://a11yproject.com/posts/how-to-hide-content/\n\n.sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip: rect(0,0,0,0);\n border: 0;\n}\n\n// Use in conjunction with .sr-only to only display content when it's focused.\n// Useful for \"Skip to main content\" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1\n// Credit: HTML5 Boilerplate\n\n.sr-only-focusable {\n &:active,\n &:focus {\n position: static;\n width: auto;\n height: auto;\n margin: 0;\n overflow: visible;\n clip: auto;\n }\n}\n\n\n// iOS \"clickable elements\" fix for role=\"button\"\n//\n// Fixes \"clickability\" issue (and more generally, the firing of events such as focus as well)\n// for traditionally non-focusable elements with role=\"button\"\n// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n\n[role=\"button\"] {\n cursor: pointer;\n}\n","// Vendor Prefixes\n//\n// All vendor mixins are deprecated as of v3.2.0 due to the introduction of\n// Autoprefixer in our Gruntfile. They will be removed in v4.\n\n// - Animations\n// - Backface visibility\n// - Box shadow\n// - Box sizing\n// - Content columns\n// - Hyphens\n// - Placeholder text\n// - Transformations\n// - Transitions\n// - User Select\n\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n -o-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\n}\n.animation-fill-mode(@fill-mode) {\n -webkit-animation-fill-mode: @fill-mode;\n animation-fill-mode: @fill-mode;\n}\n\n// Backface visibility\n// Prevent browsers from flickering when using CSS 3D transforms.\n// Default value is `visible`, but can be changed to `hidden`\n\n.backface-visibility(@visibility){\n -webkit-backface-visibility: @visibility;\n -moz-backface-visibility: @visibility;\n backface-visibility: @visibility;\n}\n\n// Drop shadows\n//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support it.\n\n.box-shadow(@shadow) {\n -webkit-box-shadow: @shadow; // iOS <4.3 & Android <4.1\n box-shadow: @shadow;\n}\n\n// Box sizing\n.box-sizing(@boxmodel) {\n -webkit-box-sizing: @boxmodel;\n -moz-box-sizing: @boxmodel;\n box-sizing: @boxmodel;\n}\n\n// CSS3 Content Columns\n.content-columns(@column-count; @column-gap: @grid-gutter-width) {\n -webkit-column-count: @column-count;\n -moz-column-count: @column-count;\n column-count: @column-count;\n -webkit-column-gap: @column-gap;\n -moz-column-gap: @column-gap;\n column-gap: @column-gap;\n}\n\n// Optional hyphenation\n.hyphens(@mode: auto) {\n word-wrap: break-word;\n -webkit-hyphens: @mode;\n -moz-hyphens: @mode;\n -ms-hyphens: @mode; // IE10+\n -o-hyphens: @mode;\n hyphens: @mode;\n}\n\n// Placeholder text\n.placeholder(@color: @input-color-placeholder) {\n // Firefox\n &::-moz-placeholder {\n color: @color;\n opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526\n }\n &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+\n &::-webkit-input-placeholder { color: @color; } // Safari and Chrome\n}\n\n// Transformations\n.scale(@ratio) {\n -webkit-transform: scale(@ratio);\n -ms-transform: scale(@ratio); // IE9 only\n -o-transform: scale(@ratio);\n transform: scale(@ratio);\n}\n.scale(@ratioX; @ratioY) {\n -webkit-transform: scale(@ratioX, @ratioY);\n -ms-transform: scale(@ratioX, @ratioY); // IE9 only\n -o-transform: scale(@ratioX, @ratioY);\n transform: scale(@ratioX, @ratioY);\n}\n.scaleX(@ratio) {\n -webkit-transform: scaleX(@ratio);\n -ms-transform: scaleX(@ratio); // IE9 only\n -o-transform: scaleX(@ratio);\n transform: scaleX(@ratio);\n}\n.scaleY(@ratio) {\n -webkit-transform: scaleY(@ratio);\n -ms-transform: scaleY(@ratio); // IE9 only\n -o-transform: scaleY(@ratio);\n transform: scaleY(@ratio);\n}\n.skew(@x; @y) {\n -webkit-transform: skewX(@x) skewY(@y);\n -ms-transform: skewX(@x) skewY(@y); // See https://github.com/twbs/bootstrap/issues/4885; IE9+\n -o-transform: skewX(@x) skewY(@y);\n transform: skewX(@x) skewY(@y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\n -o-transform: translate(@x, @y);\n transform: translate(@x, @y);\n}\n.translate3d(@x; @y; @z) {\n -webkit-transform: translate3d(@x, @y, @z);\n transform: translate3d(@x, @y, @z);\n}\n.rotate(@degrees) {\n -webkit-transform: rotate(@degrees);\n -ms-transform: rotate(@degrees); // IE9 only\n -o-transform: rotate(@degrees);\n transform: rotate(@degrees);\n}\n.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n -o-transform: rotateX(@degrees);\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n -o-transform: rotateY(@degrees);\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n\n// Transitions\n\n.transition(@transition) {\n -webkit-transition: @transition;\n -o-transition: @transition;\n transition: @transition;\n}\n.transition-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\n}\n.transition-delay(@transition-delay) {\n -webkit-transition-delay: @transition-delay;\n transition-delay: @transition-delay;\n}\n.transition-duration(@transition-duration) {\n -webkit-transition-duration: @transition-duration;\n transition-duration: @transition-duration;\n}\n.transition-timing-function(@timing-function) {\n -webkit-transition-timing-function: @timing-function;\n transition-timing-function: @timing-function;\n}\n.transition-transform(@transition) {\n -webkit-transition: -webkit-transform @transition;\n -moz-transition: -moz-transform @transition;\n -o-transition: -o-transform @transition;\n transition: transform @transition;\n}\n\n\n// User select\n// For selecting text on the page\n\n.user-select(@select) {\n -webkit-user-select: @select;\n -moz-user-select: @select;\n -ms-user-select: @select; // IE10+\n user-select: @select;\n}\n","// WebKit-style focus\n\n.tab-focus() {\n // Default\n outline: thin dotted;\n // WebKit\n outline: 5px auto -webkit-focus-ring-color;\n outline-offset: -2px;\n}\n","// Image Mixins\n// - Responsive image\n// - Retina image\n\n\n// Responsive image\n//\n// Keep images from scaling beyond the width of their parents.\n.img-responsive(@display: block) {\n display: @display;\n max-width: 100%; // Part 1: Set a maximum relative to the parent\n height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching\n}\n\n\n// Retina image\n//\n// Short retina mixin for setting background-image and -size. Note that the\n// spelling of `min--moz-device-pixel-ratio` is intentional.\n.img-retina(@file-1x; @file-2x; @width-1x; @height-1x) {\n background-image: url(\"@{file-1x}\");\n\n @media\n only screen and (-webkit-min-device-pixel-ratio: 2),\n only screen and ( min--moz-device-pixel-ratio: 2),\n only screen and ( -o-min-device-pixel-ratio: 2/1),\n only screen and ( min-device-pixel-ratio: 2),\n only screen and ( min-resolution: 192dpi),\n only screen and ( min-resolution: 2dppx) {\n background-image: url(\"@{file-2x}\");\n background-size: @width-1x @height-1x;\n }\n}\n","//\n// Typography\n// --------------------------------------------------\n\n\n// Headings\n// -------------------------\n\nh1, h2, h3, h4, h5, h6,\n.h1, .h2, .h3, .h4, .h5, .h6 {\n font-family: @headings-font-family;\n font-weight: @headings-font-weight;\n line-height: @headings-line-height;\n color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 300;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\n font-size: (@font-size-base * 1.5);\n }\n}\n\n\n// Emphasis & misc\n// -------------------------\n\n// Ex: (12px small font / 14px base font) * 100% = about 85%\nsmall,\n.small {\n font-size: floor((100% * @font-size-small / @font-size-base));\n}\n\nmark,\n.mark {\n background-color: @state-warning-bg;\n padding: .2em;\n}\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n.text-nowrap { white-space: nowrap; }\n\n// Transformation\n.text-lowercase { text-transform: lowercase; }\n.text-uppercase { text-transform: uppercase; }\n.text-capitalize { text-transform: capitalize; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\n\n\n// Page header\n// -------------------------\n\n.page-header {\n padding-bottom: ((@line-height-computed / 2) - 1);\n margin: (@line-height-computed * 2) 0 @line-height-computed;\n border-bottom: 1px solid @page-header-border-color;\n}\n\n\n// Lists\n// -------------------------\n\n// Unordered and Ordered lists\nul,\nol {\n margin-top: 0;\n margin-bottom: (@line-height-computed / 2);\n ul,\n ol {\n margin-bottom: 0;\n }\n}\n\n// List options\n\n// Unstyled keeps list items block level, just removes default browser padding and list-style\n.list-unstyled {\n padding-left: 0;\n list-style: none;\n}\n\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\n margin-bottom: @line-height-computed;\n}\ndt,\ndd {\n line-height: @line-height-base;\n}\ndt {\n font-weight: bold;\n}\ndd {\n margin-left: 0; // Undo browser default\n}\n\n// Horizontal description lists\n//\n// Defaults to being stacked without any of the below styles applied, until the\n// grid breakpoint is reached (default of ~768px).\n\n.dl-horizontal {\n dd {\n &:extend(.clearfix all); // Clear the floated `dt` if an empty `dd` is present\n }\n\n @media (min-width: @grid-float-breakpoint) {\n dt {\n float: left;\n width: (@dl-horizontal-offset - 20);\n clear: left;\n text-align: right;\n .text-overflow();\n }\n dd {\n margin-left: @dl-horizontal-offset;\n }\n }\n}\n\n\n// Misc\n// -------------------------\n\n// Abbreviations and acronyms\nabbr[title],\n// Add data-* attribute to help out our tooltip plugin, per https://github.com/twbs/bootstrap/issues/5257\nabbr[data-original-title] {\n cursor: help;\n border-bottom: 1px dotted @abbr-border-color;\n}\n.initialism {\n font-size: 90%;\n .text-uppercase();\n}\n\n// Blockquotes\nblockquote {\n padding: (@line-height-computed / 2) @line-height-computed;\n margin: 0 0 @line-height-computed;\n font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","// Typography\n\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover,\n a&:focus {\n color: darken(@color, 10%);\n }\n}\n","// Contextual backgrounds\n\n.bg-variant(@color) {\n background-color: @color;\n a&:hover,\n a&:focus {\n background-color: darken(@color, 10%);\n }\n}\n","// Text overflow\n// Requires inline-block or block for proper styling\n\n.text-overflow() {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\n font-family: @font-family-monospace;\n}\n\n// Inline code\ncode {\n padding: 2px 4px;\n font-size: 90%;\n color: @code-color;\n background-color: @code-bg;\n border-radius: @border-radius-base;\n}\n\n// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\n\n kbd {\n padding: 0;\n font-size: 100%;\n font-weight: bold;\n box-shadow: none;\n }\n}\n\n// Blocks of code\npre {\n display: block;\n padding: ((@line-height-computed - 1) / 2);\n margin: 0 0 (@line-height-computed / 2);\n font-size: (@font-size-base - 1); // 14px to 13px\n line-height: @line-height-base;\n word-break: break-all;\n word-wrap: break-word;\n color: @pre-color;\n background-color: @pre-bg;\n border: 1px solid @pre-border-color;\n border-radius: @border-radius-base;\n\n // Account for some code outputs that place code tags in pre tags\n code {\n padding: 0;\n font-size: inherit;\n color: inherit;\n white-space: pre-wrap;\n background-color: transparent;\n border-radius: 0;\n }\n}\n\n// Enable scrollable blocks of code\n.pre-scrollable {\n max-height: @pre-scrollable-max-height;\n overflow-y: scroll;\n}\n","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","// Grid system\n//\n// Generate semantic grid columns with these mixins.\n\n// Centered container element\n.container-fixed(@gutter: @grid-gutter-width) {\n margin-right: auto;\n margin-left: auto;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n &:extend(.clearfix all);\n}\n\n// Creates a wrapper for a series of columns\n.make-row(@gutter: @grid-gutter-width) {\n margin-left: ceil((@gutter / -2));\n margin-right: floor((@gutter / -2));\n &:extend(.clearfix all);\n}\n\n// Generate the extra small columns\n.make-xs-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n float: left;\n width: percentage((@columns / @grid-columns));\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n margin-left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-push(@columns) {\n left: percentage((@columns / @grid-columns));\n}\n.make-xs-column-pull(@columns) {\n right: percentage((@columns / @grid-columns));\n}\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n","// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n position: relative;\n // Prevent columns from collapsing when empty\n min-height: 1px;\n // Inner gutter via padding\n padding-left: ceil((@grid-gutter-width / 2));\n padding-right: floor((@grid-gutter-width / 2));\n }\n }\n .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index > 0) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) and (@index = 0) {\n .col-@{class}-push-0 {\n left: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index > 0) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) and (@index = 0) {\n .col-@{class}-pull-0 {\n right: auto;\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\n}\n","//\n// Tables\n// --------------------------------------------------\n\n\ntable {\n background-color: @table-bg;\n}\ncaption {\n padding-top: @table-cell-padding;\n padding-bottom: @table-cell-padding;\n color: @text-muted;\n text-align: left;\n}\nth {\n text-align: left;\n}\n\n\n// Baseline styles\n\n.table {\n width: 100%;\n max-width: 100%;\n margin-bottom: @line-height-computed;\n // Cells\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-cell-padding;\n line-height: @line-height-base;\n vertical-align: top;\n border-top: 1px solid @table-border-color;\n }\n }\n }\n // Bottom align for column headings\n > thead > tr > th {\n vertical-align: bottom;\n border-bottom: 2px solid @table-border-color;\n }\n // Remove top border from thead by default\n > caption + thead,\n > colgroup + thead,\n > thead:first-child {\n > tr:first-child {\n > th,\n > td {\n border-top: 0;\n }\n }\n }\n // Account for multiple tbody instances\n > tbody + tbody {\n border-top: 2px solid @table-border-color;\n }\n\n // Nesting\n .table {\n background-color: @body-bg;\n }\n}\n\n\n// Condensed table w/ half padding\n\n.table-condensed {\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n padding: @table-condensed-cell-padding;\n }\n }\n }\n}\n\n\n// Bordered version\n//\n// Add borders all around the table and between all the columns.\n\n.table-bordered {\n border: 1px solid @table-border-color;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n border: 1px solid @table-border-color;\n }\n }\n }\n > thead > tr {\n > th,\n > td {\n border-bottom-width: 2px;\n }\n }\n}\n\n\n// Zebra-striping\n//\n// Default zebra-stripe styles (alternating gray and transparent backgrounds)\n\n.table-striped {\n > tbody > tr:nth-of-type(odd) {\n background-color: @table-bg-accent;\n }\n}\n\n\n// Hover effect\n//\n// Placed here since it has to come after the potential zebra striping\n\n.table-hover {\n > tbody > tr:hover {\n background-color: @table-bg-hover;\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-cell;\n }\n }\n}\n\n\n// Table backgrounds\n//\n// Exact selectors below required to override `.table-striped` and prevent\n// inheritance to nested tables.\n\n// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` and we'll make them mobile friendly\n// by enabling horizontal scrolling. Only applies <768px. Everything above that\n// will display normally.\n\n.table-responsive {\n overflow-x: auto;\n min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837)\n\n @media screen and (max-width: @screen-xs-max) {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\n\n // Ensure the content doesn't wrap\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th,\n > td {\n white-space: nowrap;\n }\n }\n }\n }\n\n // Special overrides for the bordered tables\n > .table-bordered {\n border: 0;\n\n // Nuke the appropriate borders so that the parent can handle them\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","// Tables\n\n.table-row-variant(@state; @background) {\n // Exact selectors below required to override `.table-striped` and prevent\n // inheritance to nested tables.\n .table > thead > tr,\n .table > tbody > tr,\n .table > tfoot > tr {\n > td.@{state},\n > th.@{state},\n &.@{state} > td,\n &.@{state} > th {\n background-color: @background;\n }\n }\n\n // Hover states for `.table-hover`\n // Note: this is not available for cells or rows within `thead` or `tfoot`.\n .table-hover > tbody > tr {\n > td.@{state}:hover,\n > th.@{state}:hover,\n &.@{state}:hover > td,\n &:hover > .@{state},\n &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n","//\n// Forms\n// --------------------------------------------------\n\n\n// Normalize non-controls\n//\n// Restyle and baseline non-control form elements.\n\nfieldset {\n padding: 0;\n margin: 0;\n border: 0;\n // Chrome and Firefox set a `min-width: min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 0;\n}\n\nlegend {\n display: block;\n width: 100%;\n padding: 0;\n margin-bottom: @line-height-computed;\n font-size: (@font-size-base * 1.5);\n line-height: inherit;\n color: @legend-color;\n border: 0;\n border-bottom: 1px solid @legend-border-color;\n}\n\nlabel {\n display: inline-block;\n max-width: 100%; // Force IE8 to wrap long content (see https://github.com/twbs/bootstrap/issues/13141)\n margin-bottom: 5px;\n font-weight: bold;\n}\n\n\n// Normalize form controls\n//\n// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\n\n// Override content-box in Normalize (* isn't specific enough)\ninput[type=\"search\"] {\n .box-sizing(border-box);\n}\n\n// Position radios and checkboxes better\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n margin: 4px 0 0;\n margin-top: 1px \\9; // IE8-9\n line-height: normal;\n}\n\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n}\n\n\n// Common form controls\n//\n// Shared size and type resets for form controls. Apply `.form-control` to any\n// of the following form controls:\n//\n// select\n// textarea\n// input[type=\"text\"]\n// input[type=\"password\"]\n// input[type=\"datetime\"]\n// input[type=\"datetime-local\"]\n// input[type=\"date\"]\n// input[type=\"month\"]\n// input[type=\"time\"]\n// input[type=\"week\"]\n// input[type=\"number\"]\n// input[type=\"email\"]\n// input[type=\"url\"]\n// input[type=\"search\"]\n// input[type=\"tel\"]\n// input[type=\"color\"]\n\n.form-control {\n display: block;\n width: 100%;\n height: @input-height-base; // Make inputs at least the height of their button counterpart (base line-height + padding + border)\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\n background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid @input-border;\n border-radius: @input-border-radius; // Note: This has no effect on <select>s in some browsers, due to the limited stylability of <select>s in CSS.\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075));\n .transition(~\"border-color ease-in-out .15s, box-shadow ease-in-out .15s\");\n\n // Customize the `:focus` state to imitate native WebKit styles.\n .form-control-focus();\n\n // Placeholder\n .placeholder();\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // don't honor that edge case; we style them as disabled anyway.\n &[disabled],\n &[readonly],\n fieldset[disabled] & {\n background-color: @input-bg-disabled;\n opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655\n }\n\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n\n\n// Special styles for iOS temporal inputs\n//\n// In Mobile Safari, setting `display: block` on temporal inputs causes the\n// text within the input to become vertically misaligned. As a workaround, we\n// set a pixel line-height that matches the given height of the input, but only\n// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848\n//\n// Note that as of 8.3, iOS doesn't support `datetime` or `week`.\n\n@media screen and (-webkit-min-device-pixel-ratio: 0) {\n input[type=\"date\"],\n input[type=\"time\"],\n input[type=\"datetime-local\"],\n input[type=\"month\"] {\n &.form-control {\n line-height: @input-height-base;\n }\n\n &.input-sm,\n .input-group-sm & {\n line-height: @input-height-small;\n }\n\n &.input-lg,\n .input-group-lg & {\n line-height: @input-height-large;\n }\n }\n}\n\n\n// Form groups\n//\n// Designed to help with the organization and spacing of vertical forms. For\n// horizontal forms, use the predefined grid classes.\n\n.form-group {\n margin-bottom: @form-group-margin-bottom;\n}\n\n\n// Checkboxes and radios\n//\n// Indent the labels to position radios/checkboxes as hanging controls.\n\n.radio,\n.checkbox {\n position: relative;\n display: block;\n margin-top: 10px;\n margin-bottom: 10px;\n\n label {\n min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text\n padding-left: 20px;\n margin-bottom: 0;\n font-weight: normal;\n cursor: pointer;\n }\n}\n.radio input[type=\"radio\"],\n.radio-inline input[type=\"radio\"],\n.checkbox input[type=\"checkbox\"],\n.checkbox-inline input[type=\"checkbox\"] {\n position: absolute;\n margin-left: -20px;\n margin-top: 4px \\9;\n}\n\n.radio + .radio,\n.checkbox + .checkbox {\n margin-top: -5px; // Move up sibling radios or checkboxes for tighter spacing\n}\n\n// Radios and checkboxes on same line\n.radio-inline,\n.checkbox-inline {\n position: relative;\n display: inline-block;\n padding-left: 20px;\n margin-bottom: 0;\n vertical-align: middle;\n font-weight: normal;\n cursor: pointer;\n}\n.radio-inline + .radio-inline,\n.checkbox-inline + .checkbox-inline {\n margin-top: 0;\n margin-left: 10px; // space out consecutive inline controls\n}\n\n// Apply same disabled cursor tweak as for inputs\n// Some special care is needed because <label>s don't inherit their parent's `cursor`.\n//\n// Note: Neither radios nor checkboxes can be readonly.\ninput[type=\"radio\"],\ninput[type=\"checkbox\"] {\n &[disabled],\n &.disabled,\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n}\n// These classes are used directly on <label>s\n.radio-inline,\n.checkbox-inline {\n &.disabled,\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n }\n}\n// These classes are used on elements with <label> descendants\n.radio,\n.checkbox {\n &.disabled,\n fieldset[disabled] & {\n label {\n cursor: @cursor-disabled;\n }\n }\n}\n\n\n// Static form control text\n//\n// Apply class to a `p` element to make any string of text align with labels in\n// a horizontal form layout.\n\n.form-control-static {\n // Size it appropriately next to real form controls\n padding-top: (@padding-base-vertical + 1);\n padding-bottom: (@padding-base-vertical + 1);\n // Remove default margin from `p`\n margin-bottom: 0;\n min-height: (@line-height-computed + @font-size-base);\n\n &.input-lg,\n &.input-sm {\n padding-left: 0;\n padding-right: 0;\n }\n}\n\n\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n//\n// The `.form-group-* form-control` variations are sadly duplicated to avoid the\n// issue documented in https://github.com/twbs/bootstrap/issues/15074.\n\n.input-sm {\n .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @input-border-radius-small);\n}\n.form-group-sm {\n .form-control {\n height: @input-height-small;\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n line-height: @line-height-small;\n border-radius: @input-border-radius-small;\n }\n select.form-control {\n height: @input-height-small;\n line-height: @input-height-small;\n }\n textarea.form-control,\n select[multiple].form-control {\n height: auto;\n }\n .form-control-static {\n height: @input-height-small;\n min-height: (@line-height-computed + @font-size-small);\n padding: (@padding-small-vertical + 1) @padding-small-horizontal;\n font-size: @font-size-small;\n line-height: @line-height-small;\n }\n}\n\n.input-lg {\n .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @input-border-radius-large);\n}\n.form-group-lg {\n .form-control {\n height: @input-height-large;\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-large;\n border-radius: @input-border-radius-large;\n }\n select.form-control {\n height: @input-height-large;\n line-height: @input-height-large;\n }\n textarea.form-control,\n select[multiple].form-control {\n height: auto;\n }\n .form-control-static {\n height: @input-height-large;\n min-height: (@line-height-computed + @font-size-large);\n padding: (@padding-large-vertical + 1) @padding-large-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-large;\n }\n}\n\n\n// Form control feedback states\n//\n// Apply contextual and semantic states to individual form controls.\n\n.has-feedback {\n // Enable absolute positioning\n position: relative;\n\n // Ensure icons don't overlap text\n .form-control {\n padding-right: (@input-height-base * 1.25);\n }\n}\n// Feedback icon (requires .glyphicon classes)\n.form-control-feedback {\n position: absolute;\n top: 0;\n right: 0;\n z-index: 2; // Ensure icon is above input groups\n display: block;\n width: @input-height-base;\n height: @input-height-base;\n line-height: @input-height-base;\n text-align: center;\n pointer-events: none;\n}\n.input-lg + .form-control-feedback,\n.input-group-lg + .form-control-feedback,\n.form-group-lg .form-control + .form-control-feedback {\n width: @input-height-large;\n height: @input-height-large;\n line-height: @input-height-large;\n}\n.input-sm + .form-control-feedback,\n.input-group-sm + .form-control-feedback,\n.form-group-sm .form-control + .form-control-feedback {\n width: @input-height-small;\n height: @input-height-small;\n line-height: @input-height-small;\n}\n\n// Feedback states\n.has-success {\n .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg);\n}\n\n// Reposition feedback icon if input has visible label above\n.has-feedback label {\n\n & ~ .form-control-feedback {\n top: (@line-height-computed + 5); // Height of the `label` and its margin\n }\n &.sr-only ~ .form-control-feedback {\n top: 0;\n }\n}\n\n\n// Help text\n//\n// Apply to any element you wish to create light text for placement immediately\n// below a form control. Use for general help, formatting, or instructional text.\n\n.help-block {\n display: block; // account for any element using help-block\n margin-top: 5px;\n margin-bottom: 10px;\n color: lighten(@text-color, 25%); // lighten the text some for contrast\n}\n\n\n// Inline forms\n//\n// Make forms appear inline(-block) by adding the `.form-inline` class. Inline\n// forms begin stacked on extra small (mobile) devices and then go inline when\n// viewports reach <768px.\n//\n// Requires wrapping inputs and labels with `.form-group` for proper display of\n// default HTML form controls and our custom form controls (e.g., input groups).\n//\n// Heads up! This is mixin-ed into `.navbar-form` in navbars.less.\n\n.form-inline {\n\n // Kick in the inline\n @media (min-width: @screen-sm-min) {\n // Inline-block all the things for \"inline\"\n .form-group {\n display: inline-block;\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // In navbar-form, allow folks to *not* use `.form-group`\n .form-control {\n display: inline-block;\n width: auto; // Prevent labels from stacking above inputs in `.form-group`\n vertical-align: middle;\n }\n\n // Make static controls behave like regular ones\n .form-control-static {\n display: inline-block;\n }\n\n .input-group {\n display: inline-table;\n vertical-align: middle;\n\n .input-group-addon,\n .input-group-btn,\n .form-control {\n width: auto;\n }\n }\n\n // Input groups need that 100% width though\n .input-group > .form-control {\n width: 100%;\n }\n\n .control-label {\n margin-bottom: 0;\n vertical-align: middle;\n }\n\n // Remove default margin on radios/checkboxes that were used for stacking, and\n // then undo the floating of radios and checkboxes to match.\n .radio,\n .checkbox {\n display: inline-block;\n margin-top: 0;\n margin-bottom: 0;\n vertical-align: middle;\n\n label {\n padding-left: 0;\n }\n }\n .radio input[type=\"radio\"],\n .checkbox input[type=\"checkbox\"] {\n position: relative;\n margin-left: 0;\n }\n\n // Re-override the feedback icon.\n .has-feedback .form-control-feedback {\n top: 0;\n }\n }\n}\n\n\n// Horizontal forms\n//\n// Horizontal forms are built on grid classes and allow you to create forms with\n// labels on the left and inputs on the right.\n\n.form-horizontal {\n\n // Consistent vertical alignment of radios and checkboxes\n //\n // Labels also get some reset styles, but that is scoped to a media query below.\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\n margin-top: 0;\n margin-bottom: 0;\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n }\n // Account for padding we're adding to ensure the alignment and of help text\n // and other content below items\n .radio,\n .checkbox {\n min-height: (@line-height-computed + (@padding-base-vertical + 1));\n }\n\n // Make form groups behave like rows\n .form-group {\n .make-row();\n }\n\n // Reset spacing and right align labels, but scope to media queries so that\n // labels on narrow viewports stack the same as a default form example.\n @media (min-width: @screen-sm-min) {\n .control-label {\n text-align: right;\n margin-bottom: 0;\n padding-top: (@padding-base-vertical + 1); // Default padding plus a border\n }\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n right: floor((@grid-gutter-width / 2));\n }\n\n // Form group sizes\n //\n // Quick utility class for applying `.input-lg` and `.input-sm` styles to the\n // inputs and labels within a `.form-group`.\n .form-group-lg {\n @media (min-width: @screen-sm-min) {\n .control-label {\n padding-top: ((@padding-large-vertical * @line-height-large) + 1);\n font-size: @font-size-large;\n }\n }\n }\n .form-group-sm {\n @media (min-width: @screen-sm-min) {\n .control-label {\n padding-top: (@padding-small-vertical + 1);\n font-size: @font-size-small;\n }\n }\n }\n}\n","// Form validation states\n//\n// Used in forms.less to generate the form validation CSS for warnings, errors,\n// and successes.\n\n.form-control-validation(@text-color: #555; @border-color: #ccc; @background-color: #f5f5f5) {\n // Color the label and help text\n .help-block,\n .control-label,\n .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline,\n &.radio label,\n &.checkbox label,\n &.radio-inline label,\n &.checkbox-inline label {\n color: @text-color;\n }\n // Set the border and box shadow on specific inputs to match\n .form-control {\n border-color: @border-color;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); // Redeclare so transitions work\n &:focus {\n border-color: darken(@border-color, 10%);\n @shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 6px lighten(@border-color, 20%);\n .box-shadow(@shadow);\n }\n }\n // Set validation states also for addons\n .input-group-addon {\n color: @text-color;\n border-color: @border-color;\n background-color: @background-color;\n }\n // Optional feedback icon\n .form-control-feedback {\n color: @text-color;\n }\n}\n\n\n// Form control focus state\n//\n// Generate a customized focus state and for any input with the specified color,\n// which defaults to the `@input-border-focus` variable.\n//\n// We highly encourage you to not customize the default value, but instead use\n// this to tweak colors on an as-needed basis. This aesthetic change is based on\n// WebKit's default styles, but applicable to a wider range of browsers. Its\n// usability and accessibility should be taken into account with any change.\n//\n// Example usage: change the default blue border and shadow to white for better\n// contrast against a dark gray background.\n.form-control-focus(@color: @input-border-focus) {\n @color-rgba: rgba(red(@color), green(@color), blue(@color), .6);\n &:focus {\n border-color: @color;\n outline: 0;\n .box-shadow(~\"inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px @{color-rgba}\");\n }\n}\n\n// Form control sizing\n//\n// Relative text size, padding, and border-radii changes for form controls. For\n// horizontal sizing, wrap controls in the predefined grid classes. `<select>`\n// element gets special love because it's special, and that's a fact!\n.input-size(@input-height; @padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n height: @input-height;\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n\n select& {\n height: @input-height;\n line-height: @input-height;\n }\n\n textarea&,\n select[multiple]& {\n height: auto;\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n touch-action: manipulation;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus,\n &.focus {\n .tab-focus();\n }\n }\n\n &:hover,\n &:focus,\n &.focus {\n color: @btn-default-color;\n text-decoration: none;\n }\n\n &:active,\n &.active {\n outline: 0;\n background-image: none;\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n }\n\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n cursor: @cursor-disabled;\n .opacity(.65);\n .box-shadow(none);\n }\n\n a& {\n &.disabled,\n fieldset[disabled] & {\n pointer-events: none; // Future-proof disabling of clicks on `<a>` elements\n }\n }\n}\n\n\n// Alternate buttons\n// --------------------------------------------------\n\n.btn-default {\n .button-variant(@btn-default-color; @btn-default-bg; @btn-default-border);\n}\n.btn-primary {\n .button-variant(@btn-primary-color; @btn-primary-bg; @btn-primary-border);\n}\n// Success appears as green\n.btn-success {\n .button-variant(@btn-success-color; @btn-success-bg; @btn-success-border);\n}\n// Info appears as blue-green\n.btn-info {\n .button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);\n}\n// Warning appears as orange\n.btn-warning {\n .button-variant(@btn-warning-color; @btn-warning-bg; @btn-warning-border);\n}\n// Danger and error appear as red\n.btn-danger {\n .button-variant(@btn-danger-color; @btn-danger-bg; @btn-danger-border);\n}\n\n\n// Link buttons\n// -------------------------\n\n// Make a button look and behave like a link\n.btn-link {\n color: @link-color;\n font-weight: normal;\n border-radius: 0;\n\n &,\n &:active,\n &.active,\n &[disabled],\n fieldset[disabled] & {\n background-color: transparent;\n .box-shadow(none);\n }\n &,\n &:hover,\n &:focus,\n &:active {\n border-color: transparent;\n }\n &:hover,\n &:focus {\n color: @link-hover-color;\n text-decoration: @link-hover-decoration;\n background-color: transparent;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @btn-link-disabled-color;\n text-decoration: none;\n }\n }\n}\n\n\n// Button Sizes\n// --------------------------------------------------\n\n.btn-lg {\n // line-height: ensure even-numbered height of button next to large input\n .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large);\n}\n.btn-sm {\n // line-height: ensure proper height of button next to small input\n .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n.btn-xs {\n .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small);\n}\n\n\n// Block button\n// --------------------------------------------------\n\n.btn-block {\n display: block;\n width: 100%;\n}\n\n// Vertically space out multiple block buttons\n.btn-block + .btn-block {\n margin-top: 5px;\n}\n\n// Specificity overrides\ninput[type=\"submit\"],\ninput[type=\"reset\"],\ninput[type=\"button\"] {\n &.btn-block {\n width: 100%;\n }\n}\n","// Button variants\n//\n// Easily pump out default styles, as well as :hover, :focus, :active,\n// and disabled options for all buttons\n\n.button-variant(@color; @background; @border) {\n color: @color;\n background-color: @background;\n border-color: @border;\n\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 25%);\n }\n &:hover {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n color: @color;\n background-color: darken(@background, 10%);\n border-color: darken(@border, 12%);\n\n &:hover,\n &:focus,\n &.focus {\n color: @color;\n background-color: darken(@background, 17%);\n border-color: darken(@border, 25%);\n }\n }\n &:active,\n &.active,\n .open > .dropdown-toggle& {\n background-image: none;\n }\n &.disabled,\n &[disabled],\n fieldset[disabled] & {\n &,\n &:hover,\n &:focus,\n &.focus,\n &:active,\n &.active {\n background-color: @background;\n border-color: @border;\n }\n }\n\n .badge {\n color: @background;\n background-color: @color;\n }\n}\n\n// Button sizes\n.button-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n border-radius: @border-radius;\n}\n","// Opacity\n\n.opacity(@opacity) {\n opacity: @opacity;\n // IE8 filter\n @opacity-ie: (@opacity * 100);\n filter: ~\"alpha(opacity=@{opacity-ie})\";\n}\n","//\n// Component animations\n// --------------------------------------------------\n\n// Heads up!\n//\n// We don't use the `.opacity()` mixin here since it causes a bug with text\n// fields in IE7-8. Source: https://github.com/twbs/bootstrap/pull/3552.\n\n.fade {\n opacity: 0;\n .transition(opacity .15s linear);\n &.in {\n opacity: 1;\n }\n}\n\n.collapse {\n display: none;\n\n &.in { display: block; }\n tr&.in { display: table-row; }\n tbody&.in { display: table-row-group; }\n}\n\n.collapsing {\n position: relative;\n height: 0;\n overflow: hidden;\n .transition-property(~\"height, visibility\");\n .transition-duration(.35s);\n .transition-timing-function(ease);\n}\n","//\n// Dropdown menus\n// --------------------------------------------------\n\n\n// Dropdown arrow/caret\n.caret {\n display: inline-block;\n width: 0;\n height: 0;\n margin-left: 2px;\n vertical-align: middle;\n border-top: @caret-width-base dashed;\n border-top: @caret-width-base solid ~\"\\9\"; // IE8\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\n}\n\n// The dropdown wrapper (div)\n.dropup,\n.dropdown {\n position: relative;\n}\n\n// Prevent the focus on the dropdown toggle when closing dropdowns\n.dropdown-toggle:focus {\n outline: 0;\n}\n\n// The dropdown menu (ul)\n.dropdown-menu {\n position: absolute;\n top: 100%;\n left: 0;\n z-index: @zindex-dropdown;\n display: none; // none by default, but block on \"open\" of the menu\n float: left;\n min-width: 160px;\n padding: 5px 0;\n margin: 2px 0 0; // override default ul\n list-style: none;\n font-size: @font-size-base;\n text-align: left; // Ensures proper alignment if parent has it changed (e.g., modal footer)\n background-color: @dropdown-bg;\n border: 1px solid @dropdown-fallback-border; // IE8 fallback\n border: 1px solid @dropdown-border;\n border-radius: @border-radius-base;\n .box-shadow(0 6px 12px rgba(0,0,0,.175));\n background-clip: padding-box;\n\n // Aligns the dropdown menu to right\n //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\n &.pull-right {\n right: 0;\n left: auto;\n }\n\n // Dividers (basically an hr) within the dropdown\n .divider {\n .nav-divider(@dropdown-divider-bg);\n }\n\n // Links within the dropdown menu\n > li > a {\n display: block;\n padding: 3px 20px;\n clear: both;\n font-weight: normal;\n line-height: @line-height-base;\n color: @dropdown-link-color;\n white-space: nowrap; // prevent links from randomly breaking onto new lines\n }\n}\n\n// Hover/Focus state\n.dropdown-menu > li > a {\n &:hover,\n &:focus {\n text-decoration: none;\n color: @dropdown-link-hover-color;\n background-color: @dropdown-link-hover-bg;\n }\n}\n\n// Active state\n.dropdown-menu > .active > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-active-color;\n text-decoration: none;\n outline: 0;\n background-color: @dropdown-link-active-bg;\n }\n}\n\n// Disabled state\n//\n// Gray out text and ensure the hover/focus state remains gray\n\n.dropdown-menu > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @dropdown-link-disabled-color;\n }\n\n // Nuke hover/focus effects\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: transparent;\n background-image: none; // Remove CSS gradient\n .reset-filter();\n cursor: @cursor-disabled;\n }\n}\n\n// Open state for the dropdown\n.open {\n // Show the menu\n > .dropdown-menu {\n display: block;\n }\n\n // Remove the outline when :focus is triggered\n > a {\n outline: 0;\n }\n}\n\n// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\n}\n\n// Dropdown section headers\n.dropdown-header {\n display: block;\n padding: 3px 20px;\n font-size: @font-size-small;\n line-height: @line-height-base;\n color: @dropdown-header-color;\n white-space: nowrap; // as with > li > a\n}\n\n// Backdrop to catch body clicks on mobile, etc.\n.dropdown-backdrop {\n position: fixed;\n left: 0;\n right: 0;\n bottom: 0;\n top: 0;\n z-index: (@zindex-dropdown - 10);\n}\n\n// Right aligned dropdowns\n.pull-right > .dropdown-menu {\n right: 0;\n left: auto;\n}\n\n// Allow for dropdowns to go bottom up (aka, dropup-menu)\n//\n// Just add .dropup after the standard .dropdown class and you're set, bro.\n// TODO: abstract this so that the navbar fixed styles are not placed here?\n\n.dropup,\n.navbar-fixed-bottom .dropdown {\n // Reverse the caret\n .caret {\n border-top: 0;\n border-bottom: @caret-width-base dashed;\n border-bottom: @caret-width-base solid ~\"\\9\"; // IE8\n content: \"\";\n }\n // Different positioning for bottom up menu\n .dropdown-menu {\n top: auto;\n bottom: 100%;\n margin-bottom: 2px;\n }\n}\n\n\n// Component alignment\n//\n// Reiterate per navbar.less and the modified component alignment there.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-right {\n .dropdown-menu {\n .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n","// Horizontal dividers\n//\n// Dividers (basically an hr) within dropdowns and nav lists\n\n.nav-divider(@color: #e5e5e5) {\n height: 1px;\n margin: ((@line-height-computed / 2) - 1) 0;\n overflow: hidden;\n background-color: @color;\n}\n","// Reset filters for IE\n//\n// When you need to remove a gradient background, do not forget to use this to reset\n// the IE filter for IE9 and below.\n\n.reset-filter() {\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(enabled = false)\"));\n}\n","//\n// Button groups\n// --------------------------------------------------\n\n// Make the div behave like a button\n.btn-group,\n.btn-group-vertical {\n position: relative;\n display: inline-block;\n vertical-align: middle; // match .btn alignment given font-size hack above\n > .btn {\n position: relative;\n float: left;\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active,\n &.active {\n z-index: 2;\n }\n }\n}\n\n// Prevent double borders when buttons are next to each other\n.btn-group {\n .btn + .btn,\n .btn + .btn-group,\n .btn-group + .btn,\n .btn-group + .btn-group {\n margin-left: -1px;\n }\n}\n\n// Optional: Group multiple button groups together for a toolbar\n.btn-toolbar {\n margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn,\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\n }\n}\n\n.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {\n border-radius: 0;\n}\n\n// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match\n.btn-group > .btn:first-child {\n margin-left: 0;\n &:not(:last-child):not(.dropdown-toggle) {\n .border-right-radius(0);\n }\n}\n// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it\n.btn-group > .btn:last-child:not(:first-child),\n.btn-group > .dropdown-toggle:not(:first-child) {\n .border-left-radius(0);\n}\n\n// Custom edits for including btn-groups within btn-groups (useful for including dropdown buttons within a btn-group)\n.btn-group > .btn-group {\n float: left;\n}\n.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-right-radius(0);\n }\n}\n.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-left-radius(0);\n}\n\n// On active and open, don't show outline\n.btn-group .dropdown-toggle:active,\n.btn-group.open .dropdown-toggle {\n outline: 0;\n}\n\n\n// Sizing\n//\n// Remix the default button sizing classes into new ones for easier manipulation.\n\n.btn-group-xs > .btn { &:extend(.btn-xs); }\n.btn-group-sm > .btn { &:extend(.btn-sm); }\n.btn-group-lg > .btn { &:extend(.btn-lg); }\n\n\n// Split button dropdowns\n// ----------------------\n\n// Give the line between buttons some depth\n.btn-group > .btn + .dropdown-toggle {\n padding-left: 8px;\n padding-right: 8px;\n}\n.btn-group > .btn-lg + .dropdown-toggle {\n padding-left: 12px;\n padding-right: 12px;\n}\n\n// The clickable button for toggling the menu\n// Remove the gradient and set the same inset shadow as the :active state\n.btn-group.open .dropdown-toggle {\n .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\n}\n\n\n// Reposition the caret\n.btn .caret {\n margin-left: 0;\n}\n// Carets in other button sizes\n.btn-lg .caret {\n border-width: @caret-width-large @caret-width-large 0;\n border-bottom-width: 0;\n}\n// Upside down carets for .dropup\n.dropup .btn-lg .caret {\n border-width: 0 @caret-width-large @caret-width-large;\n}\n\n\n// Vertical button groups\n// ----------------------\n\n.btn-group-vertical {\n > .btn,\n > .btn-group,\n > .btn-group > .btn {\n display: block;\n float: none;\n width: 100%;\n max-width: 100%;\n }\n\n // Clear floats so dropdown menus can be properly placed\n > .btn-group {\n &:extend(.clearfix all);\n > .btn {\n float: none;\n }\n }\n\n > .btn + .btn,\n > .btn + .btn-group,\n > .btn-group + .btn,\n > .btn-group + .btn-group {\n margin-top: -1px;\n margin-left: 0;\n }\n}\n\n.btn-group-vertical > .btn {\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n &:first-child:not(:last-child) {\n border-top-right-radius: @btn-border-radius-base;\n .border-bottom-radius(0);\n }\n &:last-child:not(:first-child) {\n border-bottom-left-radius: @btn-border-radius-base;\n .border-top-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {\n border-radius: 0;\n}\n.btn-group-vertical > .btn-group:first-child:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {\n .border-top-radius(0);\n}\n\n\n// Justified button groups\n// ----------------------\n\n.btn-group-justified {\n display: table;\n width: 100%;\n table-layout: fixed;\n border-collapse: separate;\n > .btn,\n > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\n }\n\n > .btn-group .dropdown-menu {\n left: auto;\n }\n}\n\n\n// Checkbox and radio options\n//\n// In order to support the browser's form validation feedback, powered by the\n// `required` attribute, we have to \"hide\" the inputs via `clip`. We cannot use\n// `display: none;` or `visibility: hidden;` as that also hides the popover.\n// Simply visually hiding the inputs via `opacity` would leave them clickable in\n// certain cases which is prevented by using `clip` and `pointer-events`.\n// This way, we ensure a DOM element is visible to position the popover from.\n//\n// See https://github.com/twbs/bootstrap/pull/12794 and\n// https://github.com/twbs/bootstrap/pull/14559 for more information.\n\n[data-toggle=\"buttons\"] {\n > .btn,\n > .btn-group > .btn {\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n position: absolute;\n clip: rect(0,0,0,0);\n pointer-events: none;\n }\n }\n}\n","// Single side border-radius\n\n.border-top-radius(@radius) {\n border-top-right-radius: @radius;\n border-top-left-radius: @radius;\n}\n.border-right-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-top-right-radius: @radius;\n}\n.border-bottom-radius(@radius) {\n border-bottom-right-radius: @radius;\n border-bottom-left-radius: @radius;\n}\n.border-left-radius(@radius) {\n border-bottom-left-radius: @radius;\n border-top-left-radius: @radius;\n}\n","//\n// Input groups\n// --------------------------------------------------\n\n// Base styles\n// -------------------------\n.input-group {\n position: relative; // For dropdowns\n display: table;\n border-collapse: separate; // prevent input groups from inheriting border styles from table cells when placed within a table\n\n // Undo padding and float of grid classes\n &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\n width: 100%;\n margin-bottom: 0;\n }\n}\n\n// Sizing options\n//\n// Remix the default form control sizing classes into new ones for easier\n// manipulation.\n\n.input-group-lg > .form-control,\n.input-group-lg > .input-group-addon,\n.input-group-lg > .input-group-btn > .btn {\n .input-lg();\n}\n.input-group-sm > .form-control,\n.input-group-sm > .input-group-addon,\n.input-group-sm > .input-group-btn > .btn {\n .input-sm();\n}\n\n\n// Display as table-cell\n// -------------------------\n.input-group-addon,\n.input-group-btn,\n.input-group .form-control {\n display: table-cell;\n\n &:not(:first-child):not(:last-child) {\n border-radius: 0;\n }\n}\n// Addon and addon wrapper for buttons\n.input-group-addon,\n.input-group-btn {\n width: 1%;\n white-space: nowrap;\n vertical-align: middle; // Match the inputs\n}\n\n// Text input groups\n// -------------------------\n.input-group-addon {\n padding: @padding-base-vertical @padding-base-horizontal;\n font-size: @font-size-base;\n font-weight: normal;\n line-height: 1;\n color: @input-color;\n text-align: center;\n background-color: @input-group-addon-bg;\n border: 1px solid @input-group-addon-border-color;\n border-radius: @border-radius-base;\n\n // Sizing\n &.input-sm {\n padding: @padding-small-vertical @padding-small-horizontal;\n font-size: @font-size-small;\n border-radius: @border-radius-small;\n }\n &.input-lg {\n padding: @padding-large-vertical @padding-large-horizontal;\n font-size: @font-size-large;\n border-radius: @border-radius-large;\n }\n\n // Nuke default margins from checkboxes and radios to vertically center within.\n input[type=\"radio\"],\n input[type=\"checkbox\"] {\n margin-top: 0;\n }\n}\n\n// Reset rounded corners\n.input-group .form-control:first-child,\n.input-group-addon:first-child,\n.input-group-btn:first-child > .btn,\n.input-group-btn:first-child > .btn-group > .btn,\n.input-group-btn:first-child > .dropdown-toggle,\n.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),\n.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {\n .border-right-radius(0);\n}\n.input-group-addon:first-child {\n border-right: 0;\n}\n.input-group .form-control:last-child,\n.input-group-addon:last-child,\n.input-group-btn:last-child > .btn,\n.input-group-btn:last-child > .btn-group > .btn,\n.input-group-btn:last-child > .dropdown-toggle,\n.input-group-btn:first-child > .btn:not(:first-child),\n.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {\n .border-left-radius(0);\n}\n.input-group-addon:last-child {\n border-left: 0;\n}\n\n// Button input groups\n// -------------------------\n.input-group-btn {\n position: relative;\n // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n z-index: 2;\n margin-left: -1px;\n }\n }\n}\n","//\n// Navs\n// --------------------------------------------------\n\n\n// Base class\n// --------------------------------------------------\n\n.nav {\n margin-bottom: 0;\n padding-left: 0; // Override default ul/ol\n list-style: none;\n &:extend(.clearfix all);\n\n > li {\n position: relative;\n display: block;\n\n > a {\n position: relative;\n display: block;\n padding: @nav-link-padding;\n &:hover,\n &:focus {\n text-decoration: none;\n background-color: @nav-link-hover-bg;\n }\n }\n\n // Disabled state sets text to gray and nukes hover/tab effects\n &.disabled > a {\n color: @nav-disabled-link-color;\n\n &:hover,\n &:focus {\n color: @nav-disabled-link-hover-color;\n text-decoration: none;\n background-color: transparent;\n cursor: @cursor-disabled;\n }\n }\n }\n\n // Open dropdowns\n .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @nav-link-hover-bg;\n border-color: @link-color;\n }\n }\n\n // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\n // See https://github.com/h5bp/html5-boilerplate/issues/984#issuecomment-3985989\n > li > a > img {\n max-width: none;\n }\n}\n\n\n// Tabs\n// -------------------------\n\n// Give the tabs something to sit on\n.nav-tabs {\n border-bottom: 1px solid @nav-tabs-border-color;\n > li {\n float: left;\n // Make the list-items overlay the bottom border\n margin-bottom: -1px;\n\n // Actual tabs (as links)\n > a {\n margin-right: 2px;\n line-height: @line-height-base;\n border: 1px solid transparent;\n border-radius: @border-radius-base @border-radius-base 0 0;\n &:hover {\n border-color: @nav-tabs-link-hover-border-color @nav-tabs-link-hover-border-color @nav-tabs-border-color;\n }\n }\n\n // Active state, and its :hover to override normal :hover\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-tabs-active-link-hover-color;\n background-color: @nav-tabs-active-link-hover-bg;\n border: 1px solid @nav-tabs-active-link-hover-border-color;\n border-bottom-color: transparent;\n cursor: default;\n }\n }\n }\n // pulling this in mainly for less shorthand\n &.nav-justified {\n .nav-justified();\n .nav-tabs-justified();\n }\n}\n\n\n// Pills\n// -------------------------\n.nav-pills {\n > li {\n float: left;\n\n // Links rendered as pills\n > a {\n border-radius: @nav-pills-border-radius;\n }\n + li {\n margin-left: 2px;\n }\n\n // Active state\n &.active > a {\n &,\n &:hover,\n &:focus {\n color: @nav-pills-active-link-hover-color;\n background-color: @nav-pills-active-link-hover-bg;\n }\n }\n }\n}\n\n\n// Stacked pills\n.nav-stacked {\n > li {\n float: none;\n + li {\n margin-top: 2px;\n margin-left: 0; // no need for this gap between nav items\n }\n }\n}\n\n\n// Nav variations\n// --------------------------------------------------\n\n// Justified nav links\n// -------------------------\n\n.nav-justified {\n width: 100%;\n\n > li {\n float: none;\n > a {\n text-align: center;\n margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\n// -------------------------\n\n// Specific dropdowns\n.nav-tabs .dropdown-menu {\n // make dropdown border overlap tab border\n margin-top: -1px;\n // Remove the top rounded corners here since there is a hard edge above the menu\n .border-top-radius(0);\n}\n","//\n// Navbars\n// --------------------------------------------------\n\n\n// Wrapper and base class\n//\n// Provide a static navbar from which we expand to create full-width, fixed, and\n// other navbar variations.\n\n.navbar {\n position: relative;\n min-height: @navbar-height; // Ensure a navbar always shows (e.g., without a .navbar-brand in collapsed mode)\n margin-bottom: @navbar-margin-bottom;\n border: 1px solid transparent;\n\n // Prevent floats from breaking the navbar\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: @navbar-border-radius;\n }\n}\n\n\n// Navbar heading\n//\n// Groups `.navbar-brand` and `.navbar-toggle` into a single component for easy\n// styling of responsive aspects.\n\n.navbar-header {\n &:extend(.clearfix all);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n }\n}\n\n\n// Navbar collapse (body)\n//\n// Group your navbar content into this for easy collapsing and expanding across\n// various device sizes. By default, this content is collapsed when <768px, but\n// will expand past that for a horizontal display.\n//\n// To start (on mobile devices) the navbar links, forms, and buttons are stacked\n// vertically and include a `max-height` to overflow in case you have too much\n// content for the user's viewport.\n\n.navbar-collapse {\n overflow-x: visible;\n padding-right: @navbar-padding-horizontal;\n padding-left: @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n box-shadow: inset 0 1px 0 rgba(255,255,255,.1);\n &:extend(.clearfix all);\n -webkit-overflow-scrolling: touch;\n\n &.in {\n overflow-y: auto;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border-top: 0;\n box-shadow: none;\n\n &.collapse {\n display: block !important;\n height: auto !important;\n padding-bottom: 0; // Override default setting\n overflow: visible !important;\n }\n\n &.in {\n overflow-y: visible;\n }\n\n // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-right: 0;\n }\n }\n}\n\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n .navbar-collapse {\n max-height: @navbar-collapse-max-height;\n\n @media (max-device-width: @screen-xs-min) and (orientation: landscape) {\n max-height: 200px;\n }\n }\n}\n\n\n// Both navbar header and collapse\n//\n// When a container is present, change the behavior of the header and collapse.\n\n.container,\n.container-fluid {\n > .navbar-header,\n > .navbar-collapse {\n margin-right: -@navbar-padding-horizontal;\n margin-left: -@navbar-padding-horizontal;\n\n @media (min-width: @grid-float-breakpoint) {\n margin-right: 0;\n margin-left: 0;\n }\n }\n}\n\n\n//\n// Navbar alignment options\n//\n// Display the navbar across the entirety of the page or fixed it to the top or\n// bottom of the page.\n\n// Static top (unfixed, but 100% wide) navbar\n.navbar-static-top {\n z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n\n// Fix the top/bottom navbars when screen real estate supports it\n.navbar-fixed-top,\n.navbar-fixed-bottom {\n position: fixed;\n right: 0;\n left: 0;\n z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\n border-radius: 0;\n }\n}\n.navbar-fixed-top {\n top: 0;\n border-width: 0 0 1px;\n}\n.navbar-fixed-bottom {\n bottom: 0;\n margin-bottom: 0; // override .navbar defaults\n border-width: 1px 0 0;\n}\n\n\n// Brand/project name\n\n.navbar-brand {\n float: left;\n padding: @navbar-padding-vertical @navbar-padding-horizontal;\n font-size: @font-size-large;\n line-height: @line-height-computed;\n height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n > img {\n display: block;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\n margin-left: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Navbar toggle\n//\n// Custom button for toggling the `.navbar-collapse`, powered by the collapse\n// JavaScript plugin.\n\n.navbar-toggle {\n position: relative;\n float: right;\n margin-right: @navbar-padding-horizontal;\n padding: 9px 10px;\n .navbar-vertical-align(34px);\n background-color: transparent;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: 0;\n }\n\n // Bars\n .icon-bar {\n display: block;\n width: 22px;\n height: 2px;\n border-radius: 1px;\n }\n .icon-bar + .icon-bar {\n margin-top: 4px;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n display: none;\n }\n}\n\n\n// Navbar nav links\n//\n// Builds on top of the `.nav` components with its own modifier class to make\n// the nav the full height of the horizontal nav (above 768px).\n\n.navbar-nav {\n margin: (@navbar-padding-vertical / 2) -@navbar-padding-horizontal;\n\n > li > a {\n padding-top: 10px;\n padding-bottom: 10px;\n line-height: @line-height-computed;\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n position: static;\n float: none;\n width: auto;\n margin-top: 0;\n background-color: transparent;\n border: 0;\n box-shadow: none;\n > li > a,\n .dropdown-header {\n padding: 5px 15px 5px 25px;\n }\n > li > a {\n line-height: @line-height-computed;\n &:hover,\n &:focus {\n background-image: none;\n }\n }\n }\n }\n\n // Uncollapse the nav\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin: 0;\n\n > li {\n float: left;\n > a {\n padding-top: @navbar-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n }\n}\n\n\n// Navbar form\n//\n// Extension of the `.form-inline` with some extra flavor for optimum display in\n// our navbars.\n\n.navbar-form {\n margin-left: -@navbar-padding-horizontal;\n margin-right: -@navbar-padding-horizontal;\n padding: 10px @navbar-padding-horizontal;\n border-top: 1px solid transparent;\n border-bottom: 1px solid transparent;\n @shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 1px 0 rgba(255,255,255,.1);\n .box-shadow(@shadow);\n\n // Mixin behavior for optimum display\n .form-inline();\n\n .form-group {\n @media (max-width: @grid-float-breakpoint-max) {\n margin-bottom: 5px;\n\n &:last-child {\n margin-bottom: 0;\n }\n }\n }\n\n // Vertically center in expanded, horizontal navbar\n .navbar-vertical-align(@input-height-base);\n\n // Undo 100% width for pull classes\n @media (min-width: @grid-float-breakpoint) {\n width: auto;\n border: 0;\n margin-left: 0;\n margin-right: 0;\n padding-top: 0;\n padding-bottom: 0;\n .box-shadow(none);\n }\n}\n\n\n// Dropdown menus\n\n// Menu position and menu carets\n.navbar-nav > li > .dropdown-menu {\n margin-top: 0;\n .border-top-radius(0);\n}\n// Menu position and menu caret support for dropups via extra dropup class\n.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {\n margin-bottom: 0;\n .border-top-radius(@navbar-border-radius);\n .border-bottom-radius(0);\n}\n\n\n// Buttons in navbars\n//\n// Vertically center a button within a navbar (when *not* in a form).\n\n.navbar-btn {\n .navbar-vertical-align(@input-height-base);\n\n &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\n}\n\n\n// Text in navbars\n//\n// Add a class to make any element properly align itself vertically within the navbars.\n\n.navbar-text {\n .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\n// issues with parents and chaining. Only do this when the navbar is uncollapsed\n// though so that navbar contents properly stack and align in mobile.\n//\n// Declared after the navbar components to ensure more specificity on the margins.\n\n@media (min-width: @grid-float-breakpoint) {\n .navbar-left { .pull-left(); }\n .navbar-right {\n .pull-right();\n margin-right: -@navbar-padding-horizontal;\n\n ~ .navbar-right {\n margin-right: 0;\n }\n }\n}\n\n\n// Alternate navbars\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n background-color: @navbar-default-bg;\n border-color: @navbar-default-border;\n\n .navbar-brand {\n color: @navbar-default-brand-color;\n &:hover,\n &:focus {\n color: @navbar-default-brand-hover-color;\n background-color: @navbar-default-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-default-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-default-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n\n .navbar-toggle {\n border-color: @navbar-default-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-default-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-default-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\n // Remove background color from open dropdown\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-default-link-active-bg;\n color: @navbar-default-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display when collapsed\n .open .dropdown-menu {\n > li > a {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n background-color: @navbar-default-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-active-color;\n background-color: @navbar-default-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n background-color: @navbar-default-link-disabled-bg;\n }\n }\n }\n }\n }\n\n\n // Links in navbars\n //\n // Add a class to ensure links outside the navbar nav are colored correctly.\n\n .navbar-link {\n color: @navbar-default-link-color;\n &:hover {\n color: @navbar-default-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-default-link-color;\n &:hover,\n &:focus {\n color: @navbar-default-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-default-link-disabled-color;\n }\n }\n }\n}\n\n// Inverse navbar\n\n.navbar-inverse {\n background-color: @navbar-inverse-bg;\n border-color: @navbar-inverse-border;\n\n .navbar-brand {\n color: @navbar-inverse-brand-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-brand-hover-color;\n background-color: @navbar-inverse-brand-hover-bg;\n }\n }\n\n .navbar-text {\n color: @navbar-inverse-color;\n }\n\n .navbar-nav {\n > li > a {\n color: @navbar-inverse-link-color;\n\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n\n // Darken the responsive nav toggle\n .navbar-toggle {\n border-color: @navbar-inverse-toggle-border-color;\n &:hover,\n &:focus {\n background-color: @navbar-inverse-toggle-hover-bg;\n }\n .icon-bar {\n background-color: @navbar-inverse-toggle-icon-bar-bg;\n }\n }\n\n .navbar-collapse,\n .navbar-form {\n border-color: darken(@navbar-inverse-bg, 7%);\n }\n\n // Dropdowns\n .navbar-nav {\n > .open > a {\n &,\n &:hover,\n &:focus {\n background-color: @navbar-inverse-link-active-bg;\n color: @navbar-inverse-link-active-color;\n }\n }\n\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-color: @navbar-inverse-border;\n }\n > li > a {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n background-color: @navbar-inverse-link-hover-bg;\n }\n }\n > .active > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-active-color;\n background-color: @navbar-inverse-link-active-bg;\n }\n }\n > .disabled > a {\n &,\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n background-color: @navbar-inverse-link-disabled-bg;\n }\n }\n }\n }\n }\n\n .navbar-link {\n color: @navbar-inverse-link-color;\n &:hover {\n color: @navbar-inverse-link-hover-color;\n }\n }\n\n .btn-link {\n color: @navbar-inverse-link-color;\n &:hover,\n &:focus {\n color: @navbar-inverse-link-hover-color;\n }\n &[disabled],\n fieldset[disabled] & {\n &:hover,\n &:focus {\n color: @navbar-inverse-link-disabled-color;\n }\n }\n }\n}\n","// Navbar vertical align\n//\n// Vertically center elements in the navbar.\n// Example: an element has a height of 30px, so write out `.navbar-vertical-align(30px);` to calculate the appropriate top margin.\n\n.navbar-vertical-align(@element-height) {\n margin-top: ((@navbar-height - @element-height) / 2);\n margin-bottom: ((@navbar-height - @element-height) / 2);\n}\n","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\n}\n.pull-right {\n float: right !important;\n}\n.pull-left {\n float: left !important;\n}\n\n\n// Toggling content\n// -------------------------\n\n// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\n// Pagination (multiple pages)\n// --------------------------------------------------\n.pagination {\n display: inline-block;\n padding-left: 0;\n margin: @line-height-computed 0;\n border-radius: @border-radius-base;\n\n > li {\n display: inline; // Remove list-style and block-level defaults\n > a,\n > span {\n position: relative;\n float: left; // Collapse white-space\n padding: @padding-base-vertical @padding-base-horizontal;\n line-height: @line-height-base;\n text-decoration: none;\n color: @pagination-color;\n background-color: @pagination-bg;\n border: 1px solid @pagination-border;\n margin-left: -1px;\n }\n &:first-child {\n > a,\n > span {\n margin-left: 0;\n .border-left-radius(@border-radius-base);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius-base);\n }\n }\n }\n\n > li > a,\n > li > span {\n &:hover,\n &:focus {\n z-index: 3;\n color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\n }\n }\n\n > .active > a,\n > .active > span {\n &,\n &:hover,\n &:focus {\n z-index: 2;\n color: @pagination-active-color;\n background-color: @pagination-active-bg;\n border-color: @pagination-active-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-border;\n cursor: @cursor-disabled;\n }\n }\n}\n\n// Sizing\n// --------------------------------------------------\n\n// Large\n.pagination-lg {\n .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large);\n}\n\n// Small\n.pagination-sm {\n .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small);\n}\n","// Pagination\n\n.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) {\n > li {\n > a,\n > span {\n padding: @padding-vertical @padding-horizontal;\n font-size: @font-size;\n line-height: @line-height;\n }\n &:first-child {\n > a,\n > span {\n .border-left-radius(@border-radius);\n }\n }\n &:last-child {\n > a,\n > span {\n .border-right-radius(@border-radius);\n }\n }\n }\n}\n","//\n// Pager pagination\n// --------------------------------------------------\n\n\n.pager {\n padding-left: 0;\n margin: @line-height-computed 0;\n list-style: none;\n text-align: center;\n &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-hover-bg;\n }\n }\n\n .next {\n > a,\n > span {\n float: right;\n }\n }\n\n .previous {\n > a,\n > span {\n float: left;\n }\n }\n\n .disabled {\n > a,\n > a:hover,\n > a:focus,\n > span {\n color: @pager-disabled-color;\n background-color: @pager-bg;\n cursor: @cursor-disabled;\n }\n }\n}\n","//\n// Labels\n// --------------------------------------------------\n\n.label {\n display: inline;\n padding: .2em .6em .3em;\n font-size: 75%;\n font-weight: bold;\n line-height: 1;\n color: @label-color;\n text-align: center;\n white-space: nowrap;\n vertical-align: baseline;\n border-radius: .25em;\n\n // Add hover effects, but only for links\n a& {\n &:hover,\n &:focus {\n color: @label-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Empty labels collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n}\n\n// Colors\n// Contextual variations (linked labels get darker on :hover)\n\n.label-default {\n .label-variant(@label-default-bg);\n}\n\n.label-primary {\n .label-variant(@label-primary-bg);\n}\n\n.label-success {\n .label-variant(@label-success-bg);\n}\n\n.label-info {\n .label-variant(@label-info-bg);\n}\n\n.label-warning {\n .label-variant(@label-warning-bg);\n}\n\n.label-danger {\n .label-variant(@label-danger-bg);\n}\n","// Labels\n\n.label-variant(@color) {\n background-color: @color;\n\n &[href] {\n &:hover,\n &:focus {\n background-color: darken(@color, 10%);\n }\n }\n}\n","//\n// Badges\n// --------------------------------------------------\n\n\n// Base class\n.badge {\n display: inline-block;\n min-width: 10px;\n padding: 3px 7px;\n font-size: @font-size-small;\n font-weight: @badge-font-weight;\n color: @badge-color;\n line-height: @badge-line-height;\n vertical-align: middle;\n white-space: nowrap;\n text-align: center;\n background-color: @badge-bg;\n border-radius: @badge-border-radius;\n\n // Empty badges collapse automatically (not available in IE8)\n &:empty {\n display: none;\n }\n\n // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n\n .btn-xs &,\n .btn-group-xs > .btn & {\n top: 0;\n padding: 1px 5px;\n }\n\n // Hover state, but only for links\n a& {\n &:hover,\n &:focus {\n color: @badge-link-hover-color;\n text-decoration: none;\n cursor: pointer;\n }\n }\n\n // Account for badges in navs\n .list-group-item.active > &,\n .nav-pills > .active > a > & {\n color: @badge-active-color;\n background-color: @badge-active-bg;\n }\n\n .list-group-item > & {\n float: right;\n }\n\n .list-group-item > & + & {\n margin-right: 5px;\n }\n\n .nav-pills > li > a > & {\n margin-left: 3px;\n }\n}\n","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding-top: @jumbotron-padding;\n padding-bottom: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n > hr {\n border-top-color: darken(@jumbotron-bg, 10%);\n }\n\n .container &,\n .container-fluid & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\n padding-top: (@jumbotron-padding * 1.6);\n padding-bottom: (@jumbotron-padding * 1.6);\n\n .container &,\n .container-fluid & {\n padding-left: (@jumbotron-padding * 2);\n padding-right: (@jumbotron-padding * 2);\n }\n\n h1,\n .h1 {\n font-size: @jumbotron-heading-font-size;\n }\n }\n}\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\n line-height: @line-height-base;\n background-color: @thumbnail-bg;\n border: 1px solid @thumbnail-border;\n border-radius: @thumbnail-border-radius;\n .transition(border .2s ease-in-out);\n\n > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\n// Alerts\n// --------------------------------------------------\n\n\n// Base styles\n// -------------------------\n\n.alert {\n padding: @alert-padding;\n margin-bottom: @line-height-computed;\n border: 1px solid transparent;\n border-radius: @alert-border-radius;\n\n // Headings for larger alerts\n h4 {\n margin-top: 0;\n // Specified for the h4 to prevent conflicts of changing @headings-color\n color: inherit;\n }\n\n // Provide class for links that match alerts\n .alert-link {\n font-weight: @alert-link-font-weight;\n }\n\n // Improve alignment and spacing of inner content\n > p,\n > ul {\n margin-bottom: 0;\n }\n\n > p + p {\n margin-top: 5px;\n }\n}\n\n// Dismissible alerts\n//\n// Expand the right padding and account for the close button's positioning.\n\n.alert-dismissable, // The misspelled .alert-dismissable was deprecated in 3.2.0.\n.alert-dismissible {\n padding-right: (@alert-padding + 20);\n\n // Adjust close link position\n .close {\n position: relative;\n top: -2px;\n right: -21px;\n color: inherit;\n }\n}\n\n// Alternate styles\n//\n// Generate contextual modifier classes for colorizing the alert.\n\n.alert-success {\n .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text);\n}\n\n.alert-info {\n .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text);\n}\n\n.alert-warning {\n .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text);\n}\n\n.alert-danger {\n .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text);\n}\n","// Alerts\n\n.alert-variant(@background; @border; @text-color) {\n background-color: @background;\n border-color: @border;\n color: @text-color;\n\n hr {\n border-top-color: darken(@border, 5%);\n }\n .alert-link {\n color: darken(@text-color, 10%);\n }\n}\n","//\n// Progress bars\n// --------------------------------------------------\n\n\n// Bar animations\n// -------------------------\n\n// WebKit\n@-webkit-keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n// Spec and IE10+\n@keyframes progress-bar-stripes {\n from { background-position: 40px 0; }\n to { background-position: 0 0; }\n}\n\n\n// Bar itself\n// -------------------------\n\n// Outer container\n.progress {\n overflow: hidden;\n height: @line-height-computed;\n margin-bottom: @line-height-computed;\n background-color: @progress-bg;\n border-radius: @progress-border-radius;\n .box-shadow(inset 0 1px 2px rgba(0,0,0,.1));\n}\n\n// Bar of progress\n.progress-bar {\n float: left;\n width: 0%;\n height: 100%;\n font-size: @font-size-small;\n line-height: @line-height-computed;\n color: @progress-bar-color;\n text-align: center;\n background-color: @progress-bar-bg;\n .box-shadow(inset 0 -1px 0 rgba(0,0,0,.15));\n .transition(width .6s ease);\n}\n\n// Striped bars\n//\n// `.progress-striped .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar-striped` class, which you just add to an existing\n// `.progress-bar`.\n.progress-striped .progress-bar,\n.progress-bar-striped {\n #gradient > .striped();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n//\n// `.progress.active .progress-bar` is deprecated as of v3.2.0 in favor of the\n// `.progress-bar.active` approach.\n.progress.active .progress-bar,\n.progress-bar.active {\n .animation(progress-bar-stripes 2s linear infinite);\n}\n\n\n// Variations\n// -------------------------\n\n.progress-bar-success {\n .progress-bar-variant(@progress-bar-success-bg);\n}\n\n.progress-bar-info {\n .progress-bar-variant(@progress-bar-info-bg);\n}\n\n.progress-bar-warning {\n .progress-bar-variant(@progress-bar-warning-bg);\n}\n\n.progress-bar-danger {\n .progress-bar-variant(@progress-bar-danger-bg);\n}\n","// Gradients\n\n#gradient {\n\n // Horizontal gradient, from left to right\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .horizontal(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(left, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n // Vertical gradient, from top to bottom\n //\n // Creates two color stops, start and end, by specifying a color and position for each color stop.\n // Color stops are not available in IE9 and below.\n .vertical(@start-color: #555; @end-color: #333; @start-percent: 0%; @end-percent: 100%) {\n background-image: -webkit-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Opera 12\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n background-repeat: repeat-x;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down\n }\n\n .directional(@start-color: #555; @end-color: #333; @deg: 45deg) {\n background-repeat: repeat-x;\n background-image: -webkit-linear-gradient(@deg, @start-color, @end-color); // Safari 5.1-6, Chrome 10+\n background-image: -o-linear-gradient(@deg, @start-color, @end-color); // Opera 12\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(left, @start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(to right, @start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=1)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .vertical-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: -o-linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-image: linear-gradient(@start-color, @mid-color @color-stop, @end-color);\n background-repeat: no-repeat;\n filter: e(%(\"progid:DXImageTransform.Microsoft.gradient(startColorstr='%d', endColorstr='%d', GradientType=0)\",argb(@start-color),argb(@end-color))); // IE9 and down, gets no color-stop at all for proper fallback\n }\n .radial(@inner-color: #555; @outer-color: #333) {\n background-image: -webkit-radial-gradient(circle, @inner-color, @outer-color);\n background-image: radial-gradient(circle, @inner-color, @outer-color);\n background-repeat: no-repeat;\n }\n .striped(@color: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: -o-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n }\n}\n","// Progress bars\n\n.progress-bar-variant(@color) {\n background-color: @color;\n\n // Deprecated parent class requirement as of v3.2.0\n .progress-striped & {\n #gradient > .striped();\n }\n}\n",".media {\n // Proper spacing between instances of .media\n margin-top: 15px;\n\n &:first-child {\n margin-top: 0;\n }\n}\n\n.media,\n.media-body {\n zoom: 1;\n overflow: hidden;\n}\n\n.media-body {\n width: 10000px;\n}\n\n.media-object {\n display: block;\n\n // Fix collapse in webkit from max-width: 100% and display: table-cell.\n &.img-thumbnail {\n max-width: none;\n }\n}\n\n.media-right,\n.media > .pull-right {\n padding-left: 10px;\n}\n\n.media-left,\n.media > .pull-left {\n padding-right: 10px;\n}\n\n.media-left,\n.media-right,\n.media-body {\n display: table-cell;\n vertical-align: top;\n}\n\n.media-middle {\n vertical-align: middle;\n}\n\n.media-bottom {\n vertical-align: bottom;\n}\n\n// Reset margins on headings for tighter default spacing\n.media-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n\n// Media list variation\n//\n// Undo default ul/ol styles\n.media-list {\n padding-left: 0;\n list-style: none;\n}\n","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on <ul>, <ol>, or <div>.\n\n.list-group {\n // No need to set list-style: none; since .list-group-item is block level\n margin-bottom: 20px;\n padding-left: 0; // reset padding because ul and ol\n}\n\n\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\n\n.list-group-item {\n position: relative;\n display: block;\n padding: 10px 15px;\n // Place the border on the list items and negative margin up for better styling\n margin-bottom: -1px;\n background-color: @list-group-bg;\n border: 1px solid @list-group-border;\n\n // Round the first and last items\n &:first-child {\n .border-top-radius(@list-group-border-radius);\n }\n &:last-child {\n margin-bottom: 0;\n .border-bottom-radius(@list-group-border-radius);\n }\n}\n\n\n// Interactive list items\n//\n// Use anchor or button elements instead of `li`s or `div`s to create interactive items.\n// Includes an extra `.active` modifier class for showing selected items.\n\na.list-group-item,\nbutton.list-group-item {\n color: @list-group-link-color;\n\n .list-group-item-heading {\n color: @list-group-link-heading-color;\n }\n\n // Hover state\n &:hover,\n &:focus {\n text-decoration: none;\n color: @list-group-link-hover-color;\n background-color: @list-group-hover-bg;\n }\n}\n\nbutton.list-group-item {\n width: 100%;\n text-align: left;\n}\n\n.list-group-item {\n // Disabled state\n &.disabled,\n &.disabled:hover,\n &.disabled:focus {\n background-color: @list-group-disabled-bg;\n color: @list-group-disabled-color;\n cursor: @cursor-disabled;\n\n // Force color to inherit for custom content\n .list-group-item-heading {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-disabled-text-color;\n }\n }\n\n // Active class on item itself, not parent\n &.active,\n &.active:hover,\n &.active:focus {\n z-index: 2; // Place active items above their siblings for proper border styling\n color: @list-group-active-color;\n background-color: @list-group-active-bg;\n border-color: @list-group-active-border;\n\n // Force color to inherit for custom content\n .list-group-item-heading,\n .list-group-item-heading > small,\n .list-group-item-heading > .small {\n color: inherit;\n }\n .list-group-item-text {\n color: @list-group-active-text-color;\n }\n }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\n\n.list-group-item-heading {\n margin-top: 0;\n margin-bottom: 5px;\n}\n.list-group-item-text {\n margin-bottom: 0;\n line-height: 1.3;\n}\n","// List Groups\n\n.list-group-item-variant(@state; @background; @color) {\n .list-group-item-@{state} {\n color: @color;\n background-color: @background;\n\n a&,\n button& {\n color: @color;\n\n .list-group-item-heading {\n color: inherit;\n }\n\n &:hover,\n &:focus {\n color: @color;\n background-color: darken(@background, 5%);\n }\n &.active,\n &.active:hover,\n &.active:focus {\n color: #fff;\n background-color: @color;\n border-color: @color;\n }\n }\n }\n}\n","//\n// Panels\n// --------------------------------------------------\n\n\n// Base class\n.panel {\n margin-bottom: @line-height-computed;\n background-color: @panel-bg;\n border: 1px solid transparent;\n border-radius: @panel-border-radius;\n .box-shadow(0 1px 1px rgba(0,0,0,.05));\n}\n\n// Panel contents\n.panel-body {\n padding: @panel-body-padding;\n &:extend(.clearfix all);\n}\n\n// Optional heading\n.panel-heading {\n padding: @panel-heading-padding;\n border-bottom: 1px solid transparent;\n .border-top-radius((@panel-border-radius - 1));\n\n > .dropdown .dropdown-toggle {\n color: inherit;\n }\n}\n\n// Within heading, strip any `h*` tag of its default margins for spacing.\n.panel-title {\n margin-top: 0;\n margin-bottom: 0;\n font-size: ceil((@font-size-base * 1.125));\n color: inherit;\n\n > a,\n > small,\n > .small,\n > small > a,\n > .small > a {\n color: inherit;\n }\n}\n\n// Optional footer (stays gray in every modifier class)\n.panel-footer {\n padding: @panel-footer-padding;\n background-color: @panel-footer-bg;\n border-top: 1px solid @panel-inner-border;\n .border-bottom-radius((@panel-border-radius - 1));\n}\n\n\n// List groups in panels\n//\n// By default, space out list group content from panel headings to account for\n// any kind of custom content between the two.\n\n.panel {\n > .list-group,\n > .panel-collapse > .list-group {\n margin-bottom: 0;\n\n .list-group-item {\n border-width: 1px 0;\n border-radius: 0;\n }\n\n // Add border top radius for first one\n &:first-child {\n .list-group-item:first-child {\n border-top: 0;\n .border-top-radius((@panel-border-radius - 1));\n }\n }\n\n // Add border bottom radius for last one\n &:last-child {\n .list-group-item:last-child {\n border-bottom: 0;\n .border-bottom-radius((@panel-border-radius - 1));\n }\n }\n }\n > .panel-heading + .panel-collapse > .list-group {\n .list-group-item:first-child {\n .border-top-radius(0);\n }\n }\n}\n// Collapse space between when there's no additional content.\n.panel-heading + .list-group {\n .list-group-item:first-child {\n border-top-width: 0;\n }\n}\n.list-group + .panel-footer {\n border-top-width: 0;\n}\n\n// Tables in panels\n//\n// Place a non-bordered `.table` within a panel (not within a `.panel-body`) and\n// watch it go full width.\n\n.panel {\n > .table,\n > .table-responsive > .table,\n > .panel-collapse > .table {\n margin-bottom: 0;\n\n caption {\n padding-left: @panel-body-padding;\n padding-right: @panel-body-padding;\n }\n }\n // Add border top radius for first one\n > .table:first-child,\n > .table-responsive:first-child > .table:first-child {\n .border-top-radius((@panel-border-radius - 1));\n\n > thead:first-child,\n > tbody:first-child {\n > tr:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n border-top-right-radius: (@panel-border-radius - 1);\n\n td:first-child,\n th:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-top-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n // Add border bottom radius for last one\n > .table:last-child,\n > .table-responsive:last-child > .table:last-child {\n .border-bottom-radius((@panel-border-radius - 1));\n\n > tbody:last-child,\n > tfoot:last-child {\n > tr:last-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n border-bottom-right-radius: (@panel-border-radius - 1);\n\n td:first-child,\n th:first-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-bottom-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n > .panel-body + .table,\n > .panel-body + .table-responsive,\n > .table + .panel-body,\n > .table-responsive + .panel-body {\n border-top: 1px solid @table-border-color;\n }\n > .table > tbody:first-child > tr:first-child th,\n > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n }\n > .table-bordered,\n > .table-responsive > .table-bordered {\n border: 0;\n > thead,\n > tbody,\n > tfoot {\n > tr {\n > th:first-child,\n > td:first-child {\n border-left: 0;\n }\n > th:last-child,\n > td:last-child {\n border-right: 0;\n }\n }\n }\n > thead,\n > tbody {\n > tr:first-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n > tbody,\n > tfoot {\n > tr:last-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n }\n > .table-responsive {\n border: 0;\n margin-bottom: 0;\n }\n}\n\n\n// Collapsable panels (aka, accordion)\n//\n// Wrap a series of panels in `.panel-group` to turn them into an accordion with\n// the help of our collapse JavaScript plugin.\n\n.panel-group {\n margin-bottom: @line-height-computed;\n\n // Tighten up margin so it's only between panels\n .panel {\n margin-bottom: 0;\n border-radius: @panel-border-radius;\n\n + .panel {\n margin-top: 5px;\n }\n }\n\n .panel-heading {\n border-bottom: 0;\n\n + .panel-collapse > .panel-body,\n + .panel-collapse > .list-group {\n border-top: 1px solid @panel-inner-border;\n }\n }\n\n .panel-footer {\n border-top: 0;\n + .panel-collapse .panel-body {\n border-bottom: 1px solid @panel-inner-border;\n }\n }\n}\n\n\n// Contextual variations\n.panel-default {\n .panel-variant(@panel-default-border; @panel-default-text; @panel-default-heading-bg; @panel-default-border);\n}\n.panel-primary {\n .panel-variant(@panel-primary-border; @panel-primary-text; @panel-primary-heading-bg; @panel-primary-border);\n}\n.panel-success {\n .panel-variant(@panel-success-border; @panel-success-text; @panel-success-heading-bg; @panel-success-border);\n}\n.panel-info {\n .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-border);\n}\n.panel-warning {\n .panel-variant(@panel-warning-border; @panel-warning-text; @panel-warning-heading-bg; @panel-warning-border);\n}\n.panel-danger {\n .panel-variant(@panel-danger-border; @panel-danger-text; @panel-danger-heading-bg; @panel-danger-border);\n}\n","// Panels\n\n.panel-variant(@border; @heading-text-color; @heading-bg-color; @heading-border) {\n border-color: @border;\n\n & > .panel-heading {\n color: @heading-text-color;\n background-color: @heading-bg-color;\n border-color: @heading-border;\n\n + .panel-collapse > .panel-body {\n border-top-color: @border;\n }\n .badge {\n color: @heading-bg-color;\n background-color: @heading-text-color;\n }\n }\n & > .panel-footer {\n + .panel-collapse > .panel-body {\n border-bottom-color: @border;\n }\n }\n}\n","// Embeds responsive\n//\n// Credit: Nicolas Gallagher and SUIT CSS.\n\n.embed-responsive {\n position: relative;\n display: block;\n height: 0;\n padding: 0;\n overflow: hidden;\n\n .embed-responsive-item,\n iframe,\n embed,\n object,\n video {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n height: 100%;\n width: 100%;\n border: 0;\n }\n}\n\n// Modifier class for 16:9 aspect ratio\n.embed-responsive-16by9 {\n padding-bottom: 56.25%;\n}\n\n// Modifier class for 4:3 aspect ratio\n.embed-responsive-4by3 {\n padding-bottom: 75%;\n}\n","//\n// Wells\n// --------------------------------------------------\n\n\n// Base class\n.well {\n min-height: 20px;\n padding: 19px;\n margin-bottom: 20px;\n background-color: @well-bg;\n border: 1px solid @well-border;\n border-radius: @border-radius-base;\n .box-shadow(inset 0 1px 1px rgba(0,0,0,.05));\n blockquote {\n border-color: #ddd;\n border-color: rgba(0,0,0,.15);\n }\n}\n\n// Sizes\n.well-lg {\n padding: 24px;\n border-radius: @border-radius-large;\n}\n.well-sm {\n padding: 9px;\n border-radius: @border-radius-small;\n}\n","//\n// Close icons\n// --------------------------------------------------\n\n\n.close {\n float: right;\n font-size: (@font-size-base * 1.5);\n font-weight: @close-font-weight;\n line-height: 1;\n color: @close-color;\n text-shadow: @close-text-shadow;\n .opacity(.2);\n\n &:hover,\n &:focus {\n color: @close-color;\n text-decoration: none;\n cursor: pointer;\n .opacity(.5);\n }\n\n // Additional properties for button version\n // iOS requires the button element instead of an anchor tag.\n // If you want the anchor version, it requires `href=\"#\"`.\n // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile\n button& {\n padding: 0;\n cursor: pointer;\n background: transparent;\n border: 0;\n -webkit-appearance: none;\n }\n}\n","//\n// Modals\n// --------------------------------------------------\n\n// .modal-open - body class for killing the scroll\n// .modal - container to scroll within\n// .modal-dialog - positioning shell for the actual modal\n// .modal-content - actual modal w/ bg and corners and shit\n\n// Kill the scroll on the body\n.modal-open {\n overflow: hidden;\n}\n\n// Container that the modal scrolls within\n.modal {\n display: none;\n overflow: hidden;\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal;\n -webkit-overflow-scrolling: touch;\n\n // Prevent Chrome on Windows from adding a focus outline. For details, see\n // https://github.com/twbs/bootstrap/pull/10951.\n outline: 0;\n\n // When fading in the modal, animate it to slide down\n &.fade .modal-dialog {\n .translate(0, -25%);\n .transition-transform(~\"0.3s ease-out\");\n }\n &.in .modal-dialog { .translate(0, 0) }\n}\n.modal-open .modal {\n overflow-x: hidden;\n overflow-y: auto;\n}\n\n// Shell div to position the modal with bottom padding\n.modal-dialog {\n position: relative;\n width: auto;\n margin: 10px;\n}\n\n// Actual modal\n.modal-content {\n position: relative;\n background-color: @modal-content-bg;\n border: 1px solid @modal-content-fallback-border-color; //old browsers fallback (ie8 etc)\n border: 1px solid @modal-content-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 3px 9px rgba(0,0,0,.5));\n background-clip: padding-box;\n // Remove focus outline from opened modal\n outline: 0;\n}\n\n// Modal background\n.modal-backdrop {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n z-index: @zindex-modal-background;\n background-color: @modal-backdrop-bg;\n // Fade for backdrop\n &.fade { .opacity(0); }\n &.in { .opacity(@modal-backdrop-opacity); }\n}\n\n// Modal header\n// Top section of the modal w/ title and dismiss\n.modal-header {\n padding: @modal-title-padding;\n border-bottom: 1px solid @modal-header-border-color;\n min-height: (@modal-title-padding + @modal-title-line-height);\n}\n// Close icon\n.modal-header .close {\n margin-top: -2px;\n}\n\n// Title text within header\n.modal-title {\n margin: 0;\n line-height: @modal-title-line-height;\n}\n\n// Modal body\n// Where all modal content resides (sibling of .modal-header and .modal-footer)\n.modal-body {\n position: relative;\n padding: @modal-inner-padding;\n}\n\n// Footer (for actions)\n.modal-footer {\n padding: @modal-inner-padding;\n text-align: right; // right align buttons\n border-top: 1px solid @modal-footer-border-color;\n &:extend(.clearfix all); // clear it in case folks use .pull-* classes on buttons\n\n // Properly space out buttons\n .btn + .btn {\n margin-left: 5px;\n margin-bottom: 0; // account for input[type=\"submit\"] which gets the bottom margin like all other inputs\n }\n // but override that for button groups\n .btn-group .btn + .btn {\n margin-left: -1px;\n }\n // and override it for block buttons as well\n .btn-block + .btn-block {\n margin-left: 0;\n }\n}\n\n// Measure scrollbar width for padding body during modal show/hide\n.modal-scrollbar-measure {\n position: absolute;\n top: -9999px;\n width: 50px;\n height: 50px;\n overflow: scroll;\n}\n\n// Scale up the modal\n@media (min-width: @screen-sm-min) {\n // Automatically set modal's width for larger viewports\n .modal-dialog {\n width: @modal-md;\n margin: 30px auto;\n }\n .modal-content {\n .box-shadow(0 5px 15px rgba(0,0,0,.5));\n }\n\n // Modal sizes\n .modal-sm { width: @modal-sm; }\n}\n\n@media (min-width: @screen-md-min) {\n .modal-lg { width: @modal-lg; }\n}\n","//\n// Tooltips\n// --------------------------------------------------\n\n\n// Base class\n.tooltip {\n position: absolute;\n z-index: @zindex-tooltip;\n display: block;\n // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.\n // So reset our font and text properties to avoid inheriting weird values.\n .reset-text();\n font-size: @font-size-small;\n\n .opacity(0);\n\n &.in { .opacity(@tooltip-opacity); }\n &.top { margin-top: -3px; padding: @tooltip-arrow-width 0; }\n &.right { margin-left: 3px; padding: 0 @tooltip-arrow-width; }\n &.bottom { margin-top: 3px; padding: @tooltip-arrow-width 0; }\n &.left { margin-left: -3px; padding: 0 @tooltip-arrow-width; }\n}\n\n// Wrapper for the tooltip content\n.tooltip-inner {\n max-width: @tooltip-max-width;\n padding: 3px 8px;\n color: @tooltip-color;\n text-align: center;\n background-color: @tooltip-bg;\n border-radius: @border-radius-base;\n}\n\n// Arrows\n.tooltip-arrow {\n position: absolute;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n}\n// Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1\n.tooltip {\n &.top .tooltip-arrow {\n bottom: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-left .tooltip-arrow {\n bottom: 0;\n right: @tooltip-arrow-width;\n margin-bottom: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.top-right .tooltip-arrow {\n bottom: 0;\n left: @tooltip-arrow-width;\n margin-bottom: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width 0;\n border-top-color: @tooltip-arrow-color;\n }\n &.right .tooltip-arrow {\n top: 50%;\n left: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width @tooltip-arrow-width @tooltip-arrow-width 0;\n border-right-color: @tooltip-arrow-color;\n }\n &.left .tooltip-arrow {\n top: 50%;\n right: 0;\n margin-top: -@tooltip-arrow-width;\n border-width: @tooltip-arrow-width 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-left-color: @tooltip-arrow-color;\n }\n &.bottom .tooltip-arrow {\n top: 0;\n left: 50%;\n margin-left: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-left .tooltip-arrow {\n top: 0;\n right: @tooltip-arrow-width;\n margin-top: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n &.bottom-right .tooltip-arrow {\n top: 0;\n left: @tooltip-arrow-width;\n margin-top: -@tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n}\n",".reset-text() {\n font-family: @font-family-base;\n // We deliberately do NOT reset font-size.\n font-style: normal;\n font-weight: normal;\n letter-spacing: normal;\n line-break: auto;\n line-height: @line-height-base;\n text-align: left; // Fallback for where `start` is not supported\n text-align: start;\n text-decoration: none;\n text-shadow: none;\n text-transform: none;\n white-space: normal;\n word-break: normal;\n word-spacing: normal;\n word-wrap: normal;\n}\n","//\n// Popovers\n// --------------------------------------------------\n\n\n.popover {\n position: absolute;\n top: 0;\n left: 0;\n z-index: @zindex-popover;\n display: none;\n max-width: @popover-max-width;\n padding: 1px;\n // Our parent element can be arbitrary since popovers are by default inserted as a sibling of their target element.\n // So reset our font and text properties to avoid inheriting weird values.\n .reset-text();\n font-size: @font-size-base;\n\n background-color: @popover-bg;\n background-clip: padding-box;\n border: 1px solid @popover-fallback-border-color;\n border: 1px solid @popover-border-color;\n border-radius: @border-radius-large;\n .box-shadow(0 5px 10px rgba(0,0,0,.2));\n\n // Offset the popover to account for the popover arrow\n &.top { margin-top: -@popover-arrow-width; }\n &.right { margin-left: @popover-arrow-width; }\n &.bottom { margin-top: @popover-arrow-width; }\n &.left { margin-left: -@popover-arrow-width; }\n}\n\n.popover-title {\n margin: 0; // reset heading margin\n padding: 8px 14px;\n font-size: @font-size-base;\n background-color: @popover-title-bg;\n border-bottom: 1px solid darken(@popover-title-bg, 5%);\n border-radius: (@border-radius-large - 1) (@border-radius-large - 1) 0 0;\n}\n\n.popover-content {\n padding: 9px 14px;\n}\n\n// Arrows\n//\n// .arrow is outer, .arrow:after is inner\n\n.popover > .arrow {\n &,\n &:after {\n position: absolute;\n display: block;\n width: 0;\n height: 0;\n border-color: transparent;\n border-style: solid;\n }\n}\n.popover > .arrow {\n border-width: @popover-arrow-outer-width;\n}\n.popover > .arrow:after {\n border-width: @popover-arrow-width;\n content: \"\";\n}\n\n.popover {\n &.top > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-top-color: @popover-arrow-outer-color;\n bottom: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n bottom: 1px;\n margin-left: -@popover-arrow-width;\n border-bottom-width: 0;\n border-top-color: @popover-arrow-color;\n }\n }\n &.right > .arrow {\n top: 50%;\n left: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-right-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n left: 1px;\n bottom: -@popover-arrow-width;\n border-left-width: 0;\n border-right-color: @popover-arrow-color;\n }\n }\n &.bottom > .arrow {\n left: 50%;\n margin-left: -@popover-arrow-outer-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-bottom-color: @popover-arrow-outer-color;\n top: -@popover-arrow-outer-width;\n &:after {\n content: \" \";\n top: 1px;\n margin-left: -@popover-arrow-width;\n border-top-width: 0;\n border-bottom-color: @popover-arrow-color;\n }\n }\n\n &.left > .arrow {\n top: 50%;\n right: -@popover-arrow-outer-width;\n margin-top: -@popover-arrow-outer-width;\n border-right-width: 0;\n border-left-color: @popover-arrow-outer-fallback-color; // IE8 fallback\n border-left-color: @popover-arrow-outer-color;\n &:after {\n content: \" \";\n right: 1px;\n border-right-width: 0;\n border-left-color: @popover-arrow-color;\n bottom: -@popover-arrow-width;\n }\n }\n}\n","//\n// Carousel\n// --------------------------------------------------\n\n\n// Wrapper for the slide container and indicators\n.carousel {\n position: relative;\n}\n\n.carousel-inner {\n position: relative;\n overflow: hidden;\n width: 100%;\n\n > .item {\n display: none;\n position: relative;\n .transition(.6s ease-in-out left);\n\n // Account for jankitude on images\n > img,\n > a > img {\n &:extend(.img-responsive);\n line-height: 1;\n }\n\n // WebKit CSS3 transforms for supported devices\n @media all and (transform-3d), (-webkit-transform-3d) {\n .transition-transform(~'0.6s ease-in-out');\n .backface-visibility(~'hidden');\n .perspective(1000px);\n\n &.next,\n &.active.right {\n .translate3d(100%, 0, 0);\n left: 0;\n }\n &.prev,\n &.active.left {\n .translate3d(-100%, 0, 0);\n left: 0;\n }\n &.next.left,\n &.prev.right,\n &.active {\n .translate3d(0, 0, 0);\n left: 0;\n }\n }\n }\n\n > .active,\n > .next,\n > .prev {\n display: block;\n }\n\n > .active {\n left: 0;\n }\n\n > .next,\n > .prev {\n position: absolute;\n top: 0;\n width: 100%;\n }\n\n > .next {\n left: 100%;\n }\n > .prev {\n left: -100%;\n }\n > .next.left,\n > .prev.right {\n left: 0;\n }\n\n > .active.left {\n left: -100%;\n }\n > .active.right {\n left: 100%;\n }\n\n}\n\n// Left/right controls for nav\n// ---------------------------\n\n.carousel-control {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n width: @carousel-control-width;\n .opacity(@carousel-control-opacity);\n font-size: @carousel-control-font-size;\n color: @carousel-control-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n // We can't have this transition here because WebKit cancels the carousel\n // animation if you trip this while in the middle of another animation.\n\n // Set gradients for backgrounds\n &.left {\n #gradient > .horizontal(@start-color: rgba(0,0,0,.5); @end-color: rgba(0,0,0,.0001));\n }\n &.right {\n left: auto;\n right: 0;\n #gradient > .horizontal(@start-color: rgba(0,0,0,.0001); @end-color: rgba(0,0,0,.5));\n }\n\n // Hover/focus state\n &:hover,\n &:focus {\n outline: 0;\n color: @carousel-control-color;\n text-decoration: none;\n .opacity(.9);\n }\n\n // Toggles\n .icon-prev,\n .icon-next,\n .glyphicon-chevron-left,\n .glyphicon-chevron-right {\n position: absolute;\n top: 50%;\n margin-top: -10px;\n z-index: 5;\n display: inline-block;\n }\n .icon-prev,\n .glyphicon-chevron-left {\n left: 50%;\n margin-left: -10px;\n }\n .icon-next,\n .glyphicon-chevron-right {\n right: 50%;\n margin-right: -10px;\n }\n .icon-prev,\n .icon-next {\n width: 20px;\n height: 20px;\n line-height: 1;\n font-family: serif;\n }\n\n\n .icon-prev {\n &:before {\n content: '\\2039';// SINGLE LEFT-POINTING ANGLE QUOTATION MARK (U+2039)\n }\n }\n .icon-next {\n &:before {\n content: '\\203a';// SINGLE RIGHT-POINTING ANGLE QUOTATION MARK (U+203A)\n }\n }\n}\n\n// Optional indicator pips\n//\n// Add an unordered list with the following class and add a list item for each\n// slide your carousel holds.\n\n.carousel-indicators {\n position: absolute;\n bottom: 10px;\n left: 50%;\n z-index: 15;\n width: 60%;\n margin-left: -30%;\n padding-left: 0;\n list-style: none;\n text-align: center;\n\n li {\n display: inline-block;\n width: 10px;\n height: 10px;\n margin: 1px;\n text-indent: -999px;\n border: 1px solid @carousel-indicator-border-color;\n border-radius: 10px;\n cursor: pointer;\n\n // IE8-9 hack for event handling\n //\n // Internet Explorer 8-9 does not support clicks on elements without a set\n // `background-color`. We cannot use `filter` since that's not viewed as a\n // background color by the browser. Thus, a hack is needed.\n // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer\n //\n // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n // set alpha transparency for the best results possible.\n background-color: #000 \\9; // IE8\n background-color: rgba(0,0,0,0); // IE9\n }\n .active {\n margin: 0;\n width: 12px;\n height: 12px;\n background-color: @carousel-indicator-active-bg;\n }\n}\n\n// Optional captions\n// -----------------------------\n// Hidden by default for smaller viewports\n.carousel-caption {\n position: absolute;\n left: 15%;\n right: 15%;\n bottom: 20px;\n z-index: 10;\n padding-top: 20px;\n padding-bottom: 20px;\n color: @carousel-caption-color;\n text-align: center;\n text-shadow: @carousel-text-shadow;\n & .btn {\n text-shadow: none; // No shadow for button elements in carousel-caption\n }\n}\n\n\n// Scale up controls for tablets and up\n@media screen and (min-width: @screen-sm-min) {\n\n // Scale up the controls a smidge\n .carousel-control {\n .glyphicon-chevron-left,\n .glyphicon-chevron-right,\n .icon-prev,\n .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n font-size: 30px;\n }\n .glyphicon-chevron-left,\n .icon-prev {\n margin-left: -15px;\n }\n .glyphicon-chevron-right,\n .icon-next {\n margin-right: -15px;\n }\n }\n\n // Show and left align the captions\n .carousel-caption {\n left: 20%;\n right: 20%;\n padding-bottom: 30px;\n }\n\n // Move up the indicators\n .carousel-indicators {\n bottom: 20px;\n }\n}\n","// Clearfix\n//\n// For modern browsers\n// 1. The space content is one way to avoid an Opera bug when the\n// contenteditable attribute is included anywhere else in the document.\n// Otherwise it causes space to appear at the top and bottom of elements\n// that are clearfixed.\n// 2. The use of `table` rather than `block` is only necessary if using\n// `:before` to contain the top-margins of child elements.\n//\n// Source: http://nicolasgallagher.com/micro-clearfix-hack/\n\n.clearfix() {\n &:before,\n &:after {\n content: \" \"; // 1\n display: table; // 2\n }\n &:after {\n clear: both;\n }\n}\n","// Center-align a block level element\n\n.center-block() {\n display: block;\n margin-left: auto;\n margin-right: auto;\n}\n","// CSS image replacement\n//\n// Heads up! v3 launched with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n font: ~\"0/0\" a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n\n// New mixin to use as of v3.0.1\n.text-hide() {\n .hide-text();\n}\n","//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: http://getbootstrap.com/getting-started/#support-ie10-width\n// Source: http://timkadlec.com/2013/01/windows-phone-8-and-device-width/\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n width: device-width;\n}\n\n\n// Visibility utilities\n// Note: Deprecated .visible-xs, .visible-sm, .visible-md, and .visible-lg as of v3.2.0\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n .responsive-invisibility();\n}\n\n.visible-xs-block,\n.visible-xs-inline,\n.visible-xs-inline-block,\n.visible-sm-block,\n.visible-sm-inline,\n.visible-sm-inline-block,\n.visible-md-block,\n.visible-md-inline,\n.visible-md-inline-block,\n.visible-lg-block,\n.visible-lg-inline,\n.visible-lg-inline-block {\n display: none !important;\n}\n\n.visible-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-visibility();\n }\n}\n.visible-xs-block {\n @media (max-width: @screen-xs-max) {\n display: block !important;\n }\n}\n.visible-xs-inline {\n @media (max-width: @screen-xs-max) {\n display: inline !important;\n }\n}\n.visible-xs-inline-block {\n @media (max-width: @screen-xs-max) {\n display: inline-block !important;\n }\n}\n\n.visible-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-visibility();\n }\n}\n.visible-sm-block {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: block !important;\n }\n}\n.visible-sm-inline {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: inline !important;\n }\n}\n.visible-sm-inline-block {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n display: inline-block !important;\n }\n}\n\n.visible-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-visibility();\n }\n}\n.visible-md-block {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: block !important;\n }\n}\n.visible-md-inline {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: inline !important;\n }\n}\n.visible-md-inline-block {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n display: inline-block !important;\n }\n}\n\n.visible-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-visibility();\n }\n}\n.visible-lg-block {\n @media (min-width: @screen-lg-min) {\n display: block !important;\n }\n}\n.visible-lg-inline {\n @media (min-width: @screen-lg-min) {\n display: inline !important;\n }\n}\n.visible-lg-inline-block {\n @media (min-width: @screen-lg-min) {\n display: inline-block !important;\n }\n}\n\n.hidden-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-invisibility();\n }\n}\n.hidden-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-invisibility();\n }\n}\n.hidden-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-invisibility();\n }\n}\n.hidden-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-invisibility();\n }\n}\n\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n// Note: Deprecated .visible-print as of v3.2.0\n.visible-print {\n .responsive-invisibility();\n\n @media print {\n .responsive-visibility();\n }\n}\n.visible-print-block {\n display: none !important;\n\n @media print {\n display: block !important;\n }\n}\n.visible-print-inline {\n display: none !important;\n\n @media print {\n display: inline !important;\n }\n}\n.visible-print-inline-block {\n display: none !important;\n\n @media print {\n display: inline-block !important;\n }\n}\n\n.hidden-print {\n @media print {\n .responsive-invisibility();\n }\n}\n","// Responsive utilities\n\n//\n// More easily include all the states for responsive-utilities.less.\n.responsive-visibility() {\n display: block !important;\n table& { display: table !important; }\n tr& { display: table-row !important; }\n th&,\n td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n display: none !important;\n}\n"]}
\ No newline at end of file diff --git a/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot b/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot Binary files differindex 4a4ca86..b93a495 100644 --- a/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot +++ b/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.eot diff --git a/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.svg b/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.svg index e3e2dc7..94fb549 100644 --- a/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.svg +++ b/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.svg @@ -6,224 +6,283 @@ <font id="glyphicons_halflingsregular" horiz-adv-x="1200" > <font-face units-per-em="1200" ascent="960" descent="-240" /> <missing-glyph horiz-adv-x="500" /> -<glyph /> -<glyph /> -<glyph unicode="
" /> +<glyph horiz-adv-x="0" /> +<glyph horiz-adv-x="400" /> <glyph unicode=" " /> -<glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" /> -<glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" /> +<glyph unicode="*" d="M600 1100q15 0 34 -1.5t30 -3.5l11 -1q10 -2 17.5 -10.5t7.5 -18.5v-224l158 158q7 7 18 8t19 -6l106 -106q7 -8 6 -19t-8 -18l-158 -158h224q10 0 18.5 -7.5t10.5 -17.5q6 -41 6 -75q0 -15 -1.5 -34t-3.5 -30l-1 -11q-2 -10 -10.5 -17.5t-18.5 -7.5h-224l158 -158 q7 -7 8 -18t-6 -19l-106 -106q-8 -7 -19 -6t-18 8l-158 158v-224q0 -10 -7.5 -18.5t-17.5 -10.5q-41 -6 -75 -6q-15 0 -34 1.5t-30 3.5l-11 1q-10 2 -17.5 10.5t-7.5 18.5v224l-158 -158q-7 -7 -18 -8t-19 6l-106 106q-7 8 -6 19t8 18l158 158h-224q-10 0 -18.5 7.5 t-10.5 17.5q-6 41 -6 75q0 15 1.5 34t3.5 30l1 11q2 10 10.5 17.5t18.5 7.5h224l-158 158q-7 7 -8 18t6 19l106 106q8 7 19 6t18 -8l158 -158v224q0 10 7.5 18.5t17.5 10.5q41 6 75 6z" /> +<glyph unicode="+" d="M450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-350h350q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-350v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v350h-350q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5 h350v350q0 21 14.5 35.5t35.5 14.5z" /> <glyph unicode=" " /> -<glyph unicode=" " horiz-adv-x="652" /> -<glyph unicode=" " horiz-adv-x="1304" /> -<glyph unicode=" " horiz-adv-x="652" /> -<glyph unicode=" " horiz-adv-x="1304" /> -<glyph unicode=" " horiz-adv-x="434" /> -<glyph unicode=" " horiz-adv-x="326" /> -<glyph unicode=" " horiz-adv-x="217" /> -<glyph unicode=" " horiz-adv-x="217" /> -<glyph unicode=" " horiz-adv-x="163" /> +<glyph unicode="¥" d="M825 1100h250q10 0 12.5 -5t-5.5 -13l-364 -364q-6 -6 -11 -18h268q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-100h275q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-174q0 -11 -7.5 -18.5t-18.5 -7.5h-148q-11 0 -18.5 7.5t-7.5 18.5v174 h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h125v100h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h118q-5 12 -11 18l-364 364q-8 8 -5.5 13t12.5 5h250q25 0 43 -18l164 -164q8 -8 18 -8t18 8l164 164q18 18 43 18z" /> +<glyph unicode=" " horiz-adv-x="650" /> +<glyph unicode=" " horiz-adv-x="1300" /> +<glyph unicode=" " horiz-adv-x="650" /> +<glyph unicode=" " horiz-adv-x="1300" /> +<glyph unicode=" " horiz-adv-x="433" /> +<glyph unicode=" " horiz-adv-x="325" /> +<glyph unicode=" " horiz-adv-x="216" /> +<glyph unicode=" " horiz-adv-x="216" /> +<glyph unicode=" " horiz-adv-x="162" /> <glyph unicode=" " horiz-adv-x="260" /> <glyph unicode=" " horiz-adv-x="72" /> <glyph unicode=" " horiz-adv-x="260" /> -<glyph unicode=" " horiz-adv-x="326" /> -<glyph unicode="€" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" /> -<glyph unicode="−" d="M200 400h900v300h-900v-300z" /> +<glyph unicode=" " horiz-adv-x="325" /> +<glyph unicode="€" d="M744 1198q242 0 354 -189q60 -104 66 -209h-181q0 45 -17.5 82.5t-43.5 61.5t-58 40.5t-60.5 24t-51.5 7.5q-19 0 -40.5 -5.5t-49.5 -20.5t-53 -38t-49 -62.5t-39 -89.5h379l-100 -100h-300q-6 -50 -6 -100h406l-100 -100h-300q9 -74 33 -132t52.5 -91t61.5 -54.5t59 -29 t47 -7.5q22 0 50.5 7.5t60.5 24.5t58 41t43.5 61t17.5 80h174q-30 -171 -128 -278q-107 -117 -274 -117q-206 0 -324 158q-36 48 -69 133t-45 204h-217l100 100h112q1 47 6 100h-218l100 100h134q20 87 51 153.5t62 103.5q117 141 297 141z" /> +<glyph unicode="₽" d="M428 1200h350q67 0 120 -13t86 -31t57 -49.5t35 -56.5t17 -64.5t6.5 -60.5t0.5 -57v-16.5v-16.5q0 -36 -0.5 -57t-6.5 -61t-17 -65t-35 -57t-57 -50.5t-86 -31.5t-120 -13h-178l-2 -100h288q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-138v-175q0 -11 -5.5 -18 t-15.5 -7h-149q-10 0 -17.5 7.5t-7.5 17.5v175h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v100h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v475q0 10 7.5 17.5t17.5 7.5zM600 1000v-300h203q64 0 86.5 33t22.5 119q0 84 -22.5 116t-86.5 32h-203z" /> +<glyph unicode="−" d="M250 700h800q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="⌛" d="M1000 1200v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-50v-100q0 -91 -49.5 -165.5t-130.5 -109.5q81 -35 130.5 -109.5t49.5 -165.5v-150h50q21 0 35.5 -14.5t14.5 -35.5v-150h-800v150q0 21 14.5 35.5t35.5 14.5h50v150q0 91 49.5 165.5t130.5 109.5q-81 35 -130.5 109.5 t-49.5 165.5v100h-50q-21 0 -35.5 14.5t-14.5 35.5v150h800zM400 1000v-100q0 -60 32.5 -109.5t87.5 -73.5q28 -12 44 -37t16 -55t-16 -55t-44 -37q-55 -24 -87.5 -73.5t-32.5 -109.5v-150h400v150q0 60 -32.5 109.5t-87.5 73.5q-28 12 -44 37t-16 55t16 55t44 37 q55 24 87.5 73.5t32.5 109.5v100h-400z" /> <glyph unicode="◼" horiz-adv-x="500" d="M0 0z" /> -<glyph unicode="☁" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" /> -<glyph unicode="✉" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" /> -<glyph unicode="✏" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" /> -<glyph unicode="" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" /> -<glyph unicode="" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q18 -55 86 -75.5t147 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" /> -<glyph unicode="" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" /> -<glyph unicode="" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" /> -<glyph unicode="" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" /> -<glyph unicode="" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" /> -<glyph unicode="" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" /> -<glyph unicode="" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" /> -<glyph unicode="" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" /> -<glyph unicode="" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" /> -<glyph unicode="" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" /> -<glyph unicode="" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" /> -<glyph unicode="" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" /> -<glyph unicode="" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" /> -<glyph unicode="" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" /> -<glyph unicode="" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" /> -<glyph unicode="" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" /> -<glyph unicode="" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" /> -<glyph unicode="" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" /> -<glyph unicode="" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" /> -<glyph unicode="" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" /> -<glyph unicode="" d="M0 25v475l200 700h800l199 -700l1 -475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" /> -<glyph unicode="" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" /> -<glyph unicode="" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" /> -<glyph unicode="" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" /> -<glyph unicode="" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" /> -<glyph unicode="" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" /> -<glyph unicode="" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" /> -<glyph unicode="" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" /> -<glyph unicode="" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" /> -<glyph unicode="" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" /> -<glyph unicode="" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" /> -<glyph unicode="" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" /> -<glyph unicode="" d="M0 700l1 475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" /> -<glyph unicode="" d="M1 700l1 475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" /> -<glyph unicode="" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" /> -<glyph unicode="" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" /> -<glyph unicode="" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" /> -<glyph unicode="" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" /> -<glyph unicode="" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" /> -<glyph unicode="" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v71l471 -1q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" /> -<glyph unicode="" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" /> -<glyph unicode="" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " /> -<glyph unicode="" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" /> -<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" /> -<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" /> -<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" /> -<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" /> -<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" /> -<glyph unicode="" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" /> -<glyph unicode="" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" /> -<glyph unicode="" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" /> -<glyph unicode="" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " /> -<glyph unicode="" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" /> -<glyph unicode="" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" /> -<glyph unicode="" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 139t-64 210zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q61 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l567 567l-137 137l-430 -431l-146 147z" /> -<glyph unicode="" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" /> -<glyph unicode="" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" /> -<glyph unicode="" d="M200 0l900 550l-900 550v-1100z" /> -<glyph unicode="" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" /> -<glyph unicode="" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" /> -<glyph unicode="" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" /> -<glyph unicode="" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" /> -<glyph unicode="" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" /> -<glyph unicode="" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" /> -<glyph unicode="" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" /> -<glyph unicode="" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h600v200h-600v-200z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141 z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM364 700h143q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5 q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-50 0 -90.5 -12t-75 -38.5t-53.5 -74.5t-19 -114zM500 300h200v100h-200 v-100z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" /> -<glyph unicode="" d="M0 500v200h195q31 125 98.5 199.5t206.5 100.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200v-206 q149 48 201 206h-201v200h200q-25 74 -75.5 127t-124.5 77v-204h-200v203q-75 -23 -130 -77t-79 -126h209v-200h-210z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" /> -<glyph unicode="" d="M0 547l600 453v-300h600v-300h-600v-301z" /> -<glyph unicode="" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" /> -<glyph unicode="" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" /> -<glyph unicode="" d="M104 600h296v600h300v-600h298l-449 -600z" /> -<glyph unicode="" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" /> -<glyph unicode="" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" /> -<glyph unicode="" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" /> -<glyph unicode="" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5h-207q-21 0 -33 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" /> -<glyph unicode="" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111q1 1 1 6.5t-1.5 15t-3.5 17.5l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6 h-111v-100zM100 0h400v400h-400v-400zM200 900q-3 0 14 48t36 96l18 47l213 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" /> -<glyph unicode="" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" /> -<glyph unicode="" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" /> -<glyph unicode="" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" /> -<glyph unicode="" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" /> -<glyph unicode="" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 34 -48 36.5t-48 -29.5l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" /> -<glyph unicode="" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -20 -13 -28.5t-32 0.5l-94 78h-222l-94 -78q-19 -9 -32 -0.5t-13 28.5 v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" /> -<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" /> -<glyph unicode="" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" /> -<glyph unicode="" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" /> -<glyph unicode="" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" /> -<glyph unicode="" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" /> -<glyph unicode="" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" /> -<glyph unicode="" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" /> -<glyph unicode="" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" /> -<glyph unicode="" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" /> -<glyph unicode="" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" /> -<glyph unicode="" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" /> -<glyph unicode="" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" /> -<glyph unicode="" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" /> -<glyph unicode="" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM100 500v250v8v8v7t0.5 7t1.5 5.5t2 5t3 4t4.5 3.5t6 1.5t7.5 0.5h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35 q-55 337 -55 351zM1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" /> -<glyph unicode="" d="M74 350q0 21 13.5 35.5t33.5 14.5h18l117 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5q-18 -36 -18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-8 -3 -23 -8.5 t-65 -20t-103 -25t-132.5 -19.5t-158.5 -9q-125 0 -245.5 20.5t-178.5 40.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" /> -<glyph unicode="" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" /> -<glyph unicode="" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q124 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 213l100 212h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" /> -<glyph unicode="" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q124 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" /> -<glyph unicode="" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" /> -<glyph unicode="" d="M-101 651q0 72 54 110t139 38l302 -1l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 17 -10.5t26.5 -26t16.5 -36.5v-526q0 -13 -86 -93.5t-94 -80.5h-341q-16 0 -29.5 20t-19.5 41l-130 339h-107q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l107 89v502l-343 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM1000 201v600h200v-600h-200z" /> -<glyph unicode="" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6.5v7.5v6.5v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" /> -<glyph unicode="" d="M2 585q-16 -31 6 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85q0 -51 -0.5 -153.5t-0.5 -148.5q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM77 565l236 339h503 l89 -100v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" /> -<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM298 701l2 -201h300l-2 -194l402 294l-402 298v-197h-300z" /> -<glyph unicode="" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l402 -294l-2 194h300l2 201h-300v197z" /> -<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" /> -<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" /> -<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60 q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55t-20 -57q42 -71 87 -80q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q104 -3 221 112q30 29 47 47t34.5 49t20.5 62q-14 9 -37 9.5t-36 7.5q-14 7 -49 15t-52 19q-9 0 -39.5 -0.5 t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5t5.5 57.5 q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 39 2 44q31 -13 58 -14.5t39 3.5l11 4q7 36 -16.5 53.5t-64.5 28.5t-56 23q-19 -3 -37 0 q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5zM518 916q3 12 16 30t16 25q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -24 17 -66.5t17 -43.5 q-9 2 -31 5t-36 5t-32 8t-30 14zM692 1003h1h-1z" /> -<glyph unicode="" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" /> -<glyph unicode="" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" /> -<glyph unicode="" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" /> -<glyph unicode="" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" /> -<glyph unicode="" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" /> -<glyph unicode="" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM514 609q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" /> -<glyph unicode="" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -78.5 -16.5t-67.5 -51.5l-389 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23 q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60 l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" /> -<glyph unicode="" d="M80 784q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100q-71 70 -104.5 105.5t-77 89.5t-61 99 t-17.5 91zM250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-105 48.5q-74 0 -132 -83l-118 -171l-114 174q-51 80 -123 80q-60 0 -109.5 -49.5t-49.5 -118.5z" /> -<glyph unicode="" d="M57 353q0 -95 66 -159l141 -142q68 -66 159 -66q93 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-8 9 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141q7 -7 19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -17q47 -49 77 -100l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" /> -<glyph unicode="" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" /> -<glyph unicode="" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" /> -<glyph unicode="" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335q-6 1 -15.5 4t-11.5 3q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5 v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5 zM700 237q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" /> -<glyph unicode="" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -28 16.5 -69.5t28 -62.5t41.5 -72h241v-100h-197q8 -50 -2.5 -115 t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q33 1 103 -16t103 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" /> -<glyph unicode="" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" /> -<glyph unicode="" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" /> -<glyph unicode="" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" /> -<glyph unicode="" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" /> -<glyph unicode="" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" /> -<glyph unicode="" d="M217 519q8 -19 31 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8h9q14 0 26 15q11 13 274.5 321.5t264.5 308.5q14 19 5 36q-8 17 -31 17l-301 -1q1 4 78 219.5t79 227.5q2 15 -5 27l-9 9h-9q-15 0 -25 -16q-4 -6 -98 -111.5t-228.5 -257t-209.5 -237.5q-16 -19 -6 -41 z" /> -<glyph unicode="" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " /> -<glyph unicode="" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 400l697 1l3 699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l249 -237l-1 697zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" /> -<glyph unicode="" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" /> -<glyph unicode="" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" /> -<glyph unicode="" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -116q-25 -17 -43.5 -51.5t-18.5 -65.5v-359z" /> -<glyph unicode="" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" /> -<glyph unicode="" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" /> -<glyph unicode="" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q17 18 13.5 41t-22.5 37l-192 136q-19 14 -45 12t-42 -19l-118 -118q-142 101 -268 227t-227 268l118 118q17 17 20 41.5t-11 44.5 l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" /> -<glyph unicode="" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-20 0 -35 14.5t-15 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" /> -<glyph unicode="" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" /> -<glyph unicode="" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" /> -<glyph unicode="" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" /> -<glyph unicode="" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300h200 l-300 -300z" /> -<glyph unicode="" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104.5t60.5 178.5q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" /> -<glyph unicode="" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" /> -<glyph unicode="" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -11.5t1 -11.5q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" /> +<glyph unicode="☁" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -206.5q0 -121 -85 -207.5t-205 -86.5h-750q-79 0 -135.5 57t-56.5 137q0 69 42.5 122.5t108.5 67.5q-2 12 -2 37q0 153 108 260.5t260 107.5z" /> +<glyph unicode="⛺" d="M774 1193.5q16 -9.5 20.5 -27t-5.5 -33.5l-136 -187l467 -746h30q20 0 35 -18.5t15 -39.5v-42h-1200v42q0 21 15 39.5t35 18.5h30l468 746l-135 183q-10 16 -5.5 34t20.5 28t34 5.5t28 -20.5l111 -148l112 150q9 16 27 20.5t34 -5zM600 200h377l-182 112l-195 534v-646z " /> +<glyph unicode="✉" d="M25 1100h1150q10 0 12.5 -5t-5.5 -13l-564 -567q-8 -8 -18 -8t-18 8l-564 567q-8 8 -5.5 13t12.5 5zM18 882l264 -264q8 -8 8 -18t-8 -18l-264 -264q-8 -8 -13 -5.5t-5 12.5v550q0 10 5 12.5t13 -5.5zM918 618l264 264q8 8 13 5.5t5 -12.5v-550q0 -10 -5 -12.5t-13 5.5 l-264 264q-8 8 -8 18t8 18zM818 482l364 -364q8 -8 5.5 -13t-12.5 -5h-1150q-10 0 -12.5 5t5.5 13l364 364q8 8 18 8t18 -8l164 -164q8 -8 18 -8t18 8l164 164q8 8 18 8t18 -8z" /> +<glyph unicode="✏" d="M1011 1210q19 0 33 -13l153 -153q13 -14 13 -33t-13 -33l-99 -92l-214 214l95 96q13 14 32 14zM1013 800l-615 -614l-214 214l614 614zM317 96l-333 -112l110 335z" /> +<glyph unicode="" d="M700 650v-550h250q21 0 35.5 -14.5t14.5 -35.5v-50h-800v50q0 21 14.5 35.5t35.5 14.5h250v550l-500 550h1200z" /> +<glyph unicode="" d="M368 1017l645 163q39 15 63 0t24 -49v-831q0 -55 -41.5 -95.5t-111.5 -63.5q-79 -25 -147 -4.5t-86 75t25.5 111.5t122.5 82q72 24 138 8v521l-600 -155v-606q0 -42 -44 -90t-109 -69q-79 -26 -147 -5.5t-86 75.5t25.5 111.5t122.5 82.5q72 24 138 7v639q0 38 14.5 59 t53.5 34z" /> +<glyph unicode="" d="M500 1191q100 0 191 -39t156.5 -104.5t104.5 -156.5t39 -191l-1 -2l1 -5q0 -141 -78 -262l275 -274q23 -26 22.5 -44.5t-22.5 -42.5l-59 -58q-26 -20 -46.5 -20t-39.5 20l-275 274q-119 -77 -261 -77l-5 1l-2 -1q-100 0 -191 39t-156.5 104.5t-104.5 156.5t-39 191 t39 191t104.5 156.5t156.5 104.5t191 39zM500 1022q-88 0 -162 -43t-117 -117t-43 -162t43 -162t117 -117t162 -43t162 43t117 117t43 162t-43 162t-117 117t-162 43z" /> +<glyph unicode="" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104z" /> +<glyph unicode="" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429z" /> +<glyph unicode="" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429zM477 700h-240l197 -142l-74 -226 l193 139l195 -140l-74 229l192 140h-234l-78 211z" /> +<glyph unicode="" d="M600 1200q124 0 212 -88t88 -212v-250q0 -46 -31 -98t-69 -52v-75q0 -10 6 -21.5t15 -17.5l358 -230q9 -5 15 -16.5t6 -21.5v-93q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v93q0 10 6 21.5t15 16.5l358 230q9 6 15 17.5t6 21.5v75q-38 0 -69 52 t-31 98v250q0 124 88 212t212 88z" /> +<glyph unicode="" d="M25 1100h1150q10 0 17.5 -7.5t7.5 -17.5v-1050q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v1050q0 10 7.5 17.5t17.5 7.5zM100 1000v-100h100v100h-100zM875 1000h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5t17.5 -7.5h550 q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM1000 1000v-100h100v100h-100zM100 800v-100h100v100h-100zM1000 800v-100h100v100h-100zM100 600v-100h100v100h-100zM1000 600v-100h100v100h-100zM875 500h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5 t17.5 -7.5h550q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM100 400v-100h100v100h-100zM1000 400v-100h100v100h-100zM100 200v-100h100v100h-100zM1000 200v-100h100v100h-100z" /> +<glyph unicode="" d="M50 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM50 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM850 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 700h200q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5 t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h700q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M465 477l571 571q8 8 18 8t17 -8l177 -177q8 -7 8 -17t-8 -18l-783 -784q-7 -8 -17.5 -8t-17.5 8l-384 384q-8 8 -8 18t8 17l177 177q7 8 17 8t18 -8l171 -171q7 -7 18 -7t18 7z" /> +<glyph unicode="" d="M904 1083l178 -179q8 -8 8 -18.5t-8 -17.5l-267 -268l267 -268q8 -7 8 -17.5t-8 -18.5l-178 -178q-8 -8 -18.5 -8t-17.5 8l-268 267l-268 -267q-7 -8 -17.5 -8t-18.5 8l-178 178q-8 8 -8 18.5t8 17.5l267 268l-267 268q-8 7 -8 17.5t8 18.5l178 178q8 8 18.5 8t17.5 -8 l268 -267l268 268q7 7 17.5 7t18.5 -7z" /> +<glyph unicode="" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM425 900h150q10 0 17.5 -7.5t7.5 -17.5v-75h75q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5 t-17.5 -7.5h-75v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-75q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v75q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM325 800h350q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-350q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M550 1200h100q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM800 975v166q167 -62 272 -209.5t105 -331.5q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5 t-184.5 123t-123 184.5t-45.5 224q0 184 105 331.5t272 209.5v-166q-103 -55 -165 -155t-62 -220q0 -116 57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5q0 120 -62 220t-165 155z" /> +<glyph unicode="" d="M1025 1200h150q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM725 800h150q10 0 17.5 -7.5t7.5 -17.5v-750q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v750 q0 10 7.5 17.5t17.5 7.5zM425 500h150q10 0 17.5 -7.5t7.5 -17.5v-450q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v450q0 10 7.5 17.5t17.5 7.5zM125 300h150q10 0 17.5 -7.5t7.5 -17.5v-250q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5 v250q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M600 1174q33 0 74 -5l38 -152l5 -1q49 -14 94 -39l5 -2l134 80q61 -48 104 -105l-80 -134l3 -5q25 -44 39 -93l1 -6l152 -38q5 -43 5 -73q0 -34 -5 -74l-152 -38l-1 -6q-15 -49 -39 -93l-3 -5l80 -134q-48 -61 -104 -105l-134 81l-5 -3q-44 -25 -94 -39l-5 -2l-38 -151 q-43 -5 -74 -5q-33 0 -74 5l-38 151l-5 2q-49 14 -94 39l-5 3l-134 -81q-60 48 -104 105l80 134l-3 5q-25 45 -38 93l-2 6l-151 38q-6 42 -6 74q0 33 6 73l151 38l2 6q13 48 38 93l3 5l-80 134q47 61 105 105l133 -80l5 2q45 25 94 39l5 1l38 152q43 5 74 5zM600 815 q-89 0 -152 -63t-63 -151.5t63 -151.5t152 -63t152 63t63 151.5t-63 151.5t-152 63z" /> +<glyph unicode="" d="M500 1300h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-75h-1100v75q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5zM500 1200v-100h300v100h-300zM1100 900v-800q0 -41 -29.5 -70.5t-70.5 -29.5h-700q-41 0 -70.5 29.5t-29.5 70.5 v800h900zM300 800v-700h100v700h-100zM500 800v-700h100v700h-100zM700 800v-700h100v700h-100zM900 800v-700h100v700h-100z" /> +<glyph unicode="" d="M18 618l620 608q8 7 18.5 7t17.5 -7l608 -608q8 -8 5.5 -13t-12.5 -5h-175v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v375h-300v-375q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v575h-175q-10 0 -12.5 5t5.5 13z" /> +<glyph unicode="" d="M600 1200v-400q0 -41 29.5 -70.5t70.5 -29.5h300v-650q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5h450zM1000 800h-250q-21 0 -35.5 14.5t-14.5 35.5v250z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h50q10 0 17.5 -7.5t7.5 -17.5v-275h175q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M1300 0h-538l-41 400h-242l-41 -400h-538l431 1200h209l-21 -300h162l-20 300h208zM515 800l-27 -300h224l-27 300h-170z" /> +<glyph unicode="" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-450h191q20 0 25.5 -11.5t-7.5 -27.5l-327 -400q-13 -16 -32 -16t-32 16l-327 400q-13 16 -7.5 27.5t25.5 11.5h191v450q0 21 14.5 35.5t35.5 14.5zM1125 400h50q10 0 17.5 -7.5t7.5 -17.5v-350q0 -10 -7.5 -17.5t-17.5 -7.5 h-1050q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h50q10 0 17.5 -7.5t7.5 -17.5v-175h900v175q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -275q-13 -16 -32 -16t-32 16l-223 275q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z " /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM632 914l223 -275q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5l223 275q13 16 32 16 t32 -16z" /> +<glyph unicode="" d="M225 1200h750q10 0 19.5 -7t12.5 -17l186 -652q7 -24 7 -49v-425q0 -12 -4 -27t-9 -17q-12 -6 -37 -6h-1100q-12 0 -27 4t-17 8q-6 13 -6 38l1 425q0 25 7 49l185 652q3 10 12.5 17t19.5 7zM878 1000h-556q-10 0 -19 -7t-11 -18l-87 -450q-2 -11 4 -18t16 -7h150 q10 0 19.5 -7t11.5 -17l38 -152q2 -10 11.5 -17t19.5 -7h250q10 0 19.5 7t11.5 17l38 152q2 10 11.5 17t19.5 7h150q10 0 16 7t4 18l-87 450q-2 11 -11 18t-19 7z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM540 820l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" /> +<glyph unicode="" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-362q0 -10 -7.5 -17.5t-17.5 -7.5h-362q-11 0 -13 5.5t5 12.5l133 133q-109 76 -238 76q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5h150q0 -117 -45.5 -224 t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117z" /> +<glyph unicode="" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-361q0 -11 -7.5 -18.5t-18.5 -7.5h-361q-11 0 -13 5.5t5 12.5l134 134q-110 75 -239 75q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5h-150q0 117 45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117zM1027 600h150 q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5q-192 0 -348 118l-134 -134q-7 -8 -12.5 -5.5t-5.5 12.5v360q0 11 7.5 18.5t18.5 7.5h360q10 0 12.5 -5.5t-5.5 -12.5l-133 -133q110 -76 240 -76q116 0 214.5 57t155.5 155.5t57 214.5z" /> +<glyph unicode="" d="M125 1200h1050q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-1050q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM1075 1000h-850q-10 0 -17.5 -7.5t-7.5 -17.5v-850q0 -10 7.5 -17.5t17.5 -7.5h850q10 0 17.5 7.5t7.5 17.5v850 q0 10 -7.5 17.5t-17.5 7.5zM325 900h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 900h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 700h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 700h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 500h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 500h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 300h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 300h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M900 800v200q0 83 -58.5 141.5t-141.5 58.5h-300q-82 0 -141 -59t-59 -141v-200h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h900q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-100zM400 800v150q0 21 15 35.5t35 14.5h200 q20 0 35 -14.5t15 -35.5v-150h-300z" /> +<glyph unicode="" d="M125 1100h50q10 0 17.5 -7.5t7.5 -17.5v-1075h-100v1075q0 10 7.5 17.5t17.5 7.5zM1075 1052q4 0 9 -2q16 -6 16 -23v-421q0 -6 -3 -12q-33 -59 -66.5 -99t-65.5 -58t-56.5 -24.5t-52.5 -6.5q-26 0 -57.5 6.5t-52.5 13.5t-60 21q-41 15 -63 22.5t-57.5 15t-65.5 7.5 q-85 0 -160 -57q-7 -5 -15 -5q-6 0 -11 3q-14 7 -14 22v438q22 55 82 98.5t119 46.5q23 2 43 0.5t43 -7t32.5 -8.5t38 -13t32.5 -11q41 -14 63.5 -21t57 -14t63.5 -7q103 0 183 87q7 8 18 8z" /> +<glyph unicode="" d="M600 1175q116 0 227 -49.5t192.5 -131t131 -192.5t49.5 -227v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v300q0 127 -70.5 231.5t-184.5 161.5t-245 57t-245 -57t-184.5 -161.5t-70.5 -231.5v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50 q-10 0 -17.5 7.5t-7.5 17.5v300q0 116 49.5 227t131 192.5t192.5 131t227 49.5zM220 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6zM820 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460 q0 8 6 14t14 6z" /> +<glyph unicode="" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM900 668l120 120q7 7 17 7t17 -7l34 -34q7 -7 7 -17t-7 -17l-120 -120l120 -120q7 -7 7 -17 t-7 -17l-34 -34q-7 -7 -17 -7t-17 7l-120 119l-120 -119q-7 -7 -17 -7t-17 7l-34 34q-7 7 -7 17t7 17l119 120l-119 120q-7 7 -7 17t7 17l34 34q7 8 17 8t17 -8z" /> +<glyph unicode="" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6 l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238q-6 8 -4.5 18t9.5 17l29 22q7 5 15 5z" /> +<glyph unicode="" d="M967 1004h3q11 -1 17 -10q135 -179 135 -396q0 -105 -34 -206.5t-98 -185.5q-7 -9 -17 -10h-3q-9 0 -16 6l-42 34q-8 6 -9 16t5 18q111 150 111 328q0 90 -29.5 176t-84.5 157q-6 9 -5 19t10 16l42 33q7 5 15 5zM321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5 t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238 q-6 8 -4.5 18.5t9.5 16.5l29 22q7 5 15 5z" /> +<glyph unicode="" d="M500 900h100v-100h-100v-100h-400v-100h-100v600h500v-300zM1200 700h-200v-100h200v-200h-300v300h-200v300h-100v200h600v-500zM100 1100v-300h300v300h-300zM800 1100v-300h300v300h-300zM300 900h-100v100h100v-100zM1000 900h-100v100h100v-100zM300 500h200v-500 h-500v500h200v100h100v-100zM800 300h200v-100h-100v-100h-200v100h-100v100h100v200h-200v100h300v-300zM100 400v-300h300v300h-300zM300 200h-100v100h100v-100zM1200 200h-100v100h100v-100zM700 0h-100v100h100v-100zM1200 0h-300v100h300v-100z" /> +<glyph unicode="" d="M100 200h-100v1000h100v-1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 200h-200v1000h200v-1000zM400 0h-300v100h300v-100zM600 0h-100v91h100v-91zM800 0h-100v91h100v-91zM1100 0h-200v91h200v-91z" /> +<glyph unicode="" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" /> +<glyph unicode="" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM800 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-56 56l424 426l-700 700h150zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5 t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" /> +<glyph unicode="" d="M300 1200h825q75 0 75 -75v-900q0 -25 -18 -43l-64 -64q-8 -8 -13 -5.5t-5 12.5v950q0 10 -7.5 17.5t-17.5 7.5h-700q-25 0 -43 -18l-64 -64q-8 -8 -5.5 -13t12.5 -5h700q10 0 17.5 -7.5t7.5 -17.5v-950q0 -10 -7.5 -17.5t-17.5 -7.5h-850q-10 0 -17.5 7.5t-7.5 17.5v975 q0 25 18 43l139 139q18 18 43 18z" /> +<glyph unicode="" d="M250 1200h800q21 0 35.5 -14.5t14.5 -35.5v-1150l-450 444l-450 -445v1151q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M822 1200h-444q-11 0 -19 -7.5t-9 -17.5l-78 -301q-7 -24 7 -45l57 -108q6 -9 17.5 -15t21.5 -6h450q10 0 21.5 6t17.5 15l62 108q14 21 7 45l-83 301q-1 10 -9 17.5t-19 7.5zM1175 800h-150q-10 0 -21 -6.5t-15 -15.5l-78 -156q-4 -9 -15 -15.5t-21 -6.5h-550 q-10 0 -21 6.5t-15 15.5l-78 156q-4 9 -15 15.5t-21 6.5h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-650q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h750q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5 t7.5 17.5v650q0 10 -7.5 17.5t-17.5 7.5zM850 200h-500q-10 0 -19.5 -7t-11.5 -17l-38 -152q-2 -10 3.5 -17t15.5 -7h600q10 0 15.5 7t3.5 17l-38 152q-2 10 -11.5 17t-19.5 7z" /> +<glyph unicode="" d="M500 1100h200q56 0 102.5 -20.5t72.5 -50t44 -59t25 -50.5l6 -20h150q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h150q2 8 6.5 21.5t24 48t45 61t72 48t102.5 21.5zM900 800v-100 h100v100h-100zM600 730q-95 0 -162.5 -67.5t-67.5 -162.5t67.5 -162.5t162.5 -67.5t162.5 67.5t67.5 162.5t-67.5 162.5t-162.5 67.5zM600 603q43 0 73 -30t30 -73t-30 -73t-73 -30t-73 30t-30 73t30 73t73 30z" /> +<glyph unicode="" d="M681 1199l385 -998q20 -50 60 -92q18 -19 36.5 -29.5t27.5 -11.5l10 -2v-66h-417v66q53 0 75 43.5t5 88.5l-82 222h-391q-58 -145 -92 -234q-11 -34 -6.5 -57t25.5 -37t46 -20t55 -6v-66h-365v66q56 24 84 52q12 12 25 30.5t20 31.5l7 13l399 1006h93zM416 521h340 l-162 457z" /> +<glyph unicode="" d="M753 641q5 -1 14.5 -4.5t36 -15.5t50.5 -26.5t53.5 -40t50.5 -54.5t35.5 -70t14.5 -87q0 -67 -27.5 -125.5t-71.5 -97.5t-98.5 -66.5t-108.5 -40.5t-102 -13h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 24 -0.5 34t-3.5 24t-8.5 19.5t-17 13.5t-28 12.5t-42.5 11.5v71 l471 -1q57 0 115.5 -20.5t108 -57t80.5 -94t31 -124.5q0 -51 -15.5 -96.5t-38 -74.5t-45 -50.5t-38.5 -30.5zM400 700h139q78 0 130.5 48.5t52.5 122.5q0 41 -8.5 70.5t-29.5 55.5t-62.5 39.5t-103.5 13.5h-118v-350zM400 200h216q80 0 121 50.5t41 130.5q0 90 -62.5 154.5 t-156.5 64.5h-159v-400z" /> +<glyph unicode="" d="M877 1200l2 -57q-83 -19 -116 -45.5t-40 -66.5l-132 -839q-9 -49 13 -69t96 -26v-97h-500v97q186 16 200 98l173 832q3 17 3 30t-1.5 22.5t-9 17.5t-13.5 12.5t-21.5 10t-26 8.5t-33.5 10q-13 3 -19 5v57h425z" /> +<glyph unicode="" d="M1300 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM175 1000h-75v-800h75l-125 -167l-125 167h75v800h-75l125 167z" /> +<glyph unicode="" d="M1100 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-650q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v650h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM1167 50l-167 -125v75h-800v-75l-167 125l167 125v-75h800v75z" /> +<glyph unicode="" d="M50 1100h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M250 1100h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM250 500h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000 q-21 0 -35.5 14.5t-14.5 35.5zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5z" /> +<glyph unicode="" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 1100h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 800h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 500h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 500h800q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 200h800 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M400 0h-100v1100h100v-1100zM550 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM267 550l-167 -125v75h-200v100h200v75zM550 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM900 0h-100v1100h100v-1100zM50 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM1100 600h200v-100h-200v-75l-167 125l167 125v-75zM50 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M75 1000h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22zM1200 300l-300 300l300 300v-600z" /> +<glyph unicode="" d="M44 1100h1112q18 0 31 -13t13 -31v-1012q0 -18 -13 -31t-31 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13zM100 1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500h-1000zM342 884q56 0 95 -39t39 -94.5t-39 -95t-95 -39.5t-95 39.5t-39 95t39 94.5 t95 39z" /> +<glyph unicode="" d="M648 1169q117 0 216 -60t156.5 -161t57.5 -218q0 -115 -70 -258q-69 -109 -158 -225.5t-143 -179.5l-54 -62q-9 8 -25.5 24.5t-63.5 67.5t-91 103t-98.5 128t-95.5 148q-60 132 -60 249q0 88 34 169.5t91.5 142t137 96.5t166.5 36zM652.5 974q-91.5 0 -156.5 -65 t-65 -157t65 -156.5t156.5 -64.5t156.5 64.5t65 156.5t-65 157t-156.5 65z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 173v854q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57z" /> +<glyph unicode="" d="M554 1295q21 -72 57.5 -143.5t76 -130t83 -118t82.5 -117t70 -116t49.5 -126t18.5 -136.5q0 -71 -25.5 -135t-68.5 -111t-99 -82t-118.5 -54t-125.5 -23q-84 5 -161.5 34t-139.5 78.5t-99 125t-37 164.5q0 69 18 136.5t49.5 126.5t69.5 116.5t81.5 117.5t83.5 119 t76.5 131t58.5 143zM344 710q-23 -33 -43.5 -70.5t-40.5 -102.5t-17 -123q1 -37 14.5 -69.5t30 -52t41 -37t38.5 -24.5t33 -15q21 -7 32 -1t13 22l6 34q2 10 -2.5 22t-13.5 19q-5 4 -14 12t-29.5 40.5t-32.5 73.5q-26 89 6 271q2 11 -6 11q-8 1 -15 -10z" /> +<glyph unicode="" d="M1000 1013l108 115q2 1 5 2t13 2t20.5 -1t25 -9.5t28.5 -21.5q22 -22 27 -43t0 -32l-6 -10l-108 -115zM350 1100h400q50 0 105 -13l-187 -187h-368q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v182l200 200v-332 q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM1009 803l-362 -362l-161 -50l55 170l355 355z" /> +<glyph unicode="" d="M350 1100h361q-164 -146 -216 -200h-195q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-103q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M824 1073l339 -301q8 -7 8 -17.5t-8 -17.5l-340 -306q-7 -6 -12.5 -4t-6.5 11v203q-26 1 -54.5 0t-78.5 -7.5t-92 -17.5t-86 -35t-70 -57q10 59 33 108t51.5 81.5t65 58.5t68.5 40.5t67 24.5t56 13.5t40 4.5v210q1 10 6.5 12.5t13.5 -4.5z" /> +<glyph unicode="" d="M350 1100h350q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-219q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M643 639l395 395q7 7 17.5 7t17.5 -7l101 -101q7 -7 7 -17.5t-7 -17.5l-531 -532q-7 -7 -17.5 -7t-17.5 7l-248 248q-7 7 -7 17.5t7 17.5l101 101q7 7 17.5 7t17.5 -7l111 -111q8 -7 18 -7t18 7z" /> +<glyph unicode="" d="M318 918l264 264q8 8 18 8t18 -8l260 -264q7 -8 4.5 -13t-12.5 -5h-170v-200h200v173q0 10 5 12t13 -5l264 -260q8 -7 8 -17.5t-8 -17.5l-264 -265q-8 -7 -13 -5t-5 12v173h-200v-200h170q10 0 12.5 -5t-4.5 -13l-260 -264q-8 -8 -18 -8t-18 8l-264 264q-8 8 -5.5 13 t12.5 5h175v200h-200v-173q0 -10 -5 -12t-13 5l-264 265q-8 7 -8 17.5t8 17.5l264 260q8 7 13 5t5 -12v-173h200v200h-175q-10 0 -12.5 5t5.5 13z" /> +<glyph unicode="" d="M250 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5 t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M1200 1050v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-492 480q-15 14 -15 35t15 35l492 480q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25z" /> +<glyph unicode="" d="M243 1074l814 -498q18 -11 18 -26t-18 -26l-814 -498q-18 -11 -30.5 -4t-12.5 28v1000q0 21 12.5 28t30.5 -4z" /> +<glyph unicode="" d="M250 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM650 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800 q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M1100 950v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5z" /> +<glyph unicode="" d="M500 612v438q0 21 10.5 25t25.5 -10l492 -480q15 -14 15 -35t-15 -35l-492 -480q-15 -14 -25.5 -10t-10.5 25v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10z" /> +<glyph unicode="" d="M1048 1102l100 1q20 0 35 -14.5t15 -35.5l5 -1000q0 -21 -14.5 -35.5t-35.5 -14.5l-100 -1q-21 0 -35.5 14.5t-14.5 35.5l-2 437l-463 -454q-14 -15 -24.5 -10.5t-10.5 25.5l-2 437l-462 -455q-15 -14 -25.5 -9.5t-10.5 24.5l-5 1000q0 21 10.5 25.5t25.5 -10.5l466 -450 l-2 438q0 20 10.5 24.5t25.5 -9.5l466 -451l-2 438q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10l464 -453v438q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M686 1081l501 -540q15 -15 10.5 -26t-26.5 -11h-1042q-22 0 -26.5 11t10.5 26l501 540q15 15 36 15t36 -15zM150 400h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M885 900l-352 -353l352 -353l-197 -198l-552 552l552 550z" /> +<glyph unicode="" d="M1064 547l-551 -551l-198 198l353 353l-353 353l198 198z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM650 900h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-150 q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5h150v-150q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v150h150q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-150v150q0 21 -14.5 35.5t-35.5 14.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM850 700h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5 t35.5 -14.5h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM741.5 913q-12.5 0 -21.5 -9l-120 -120l-120 120q-9 9 -21.5 9 t-21.5 -9l-141 -141q-9 -9 -9 -21.5t9 -21.5l120 -120l-120 -120q-9 -9 -9 -21.5t9 -21.5l141 -141q9 -9 21.5 -9t21.5 9l120 120l120 -120q9 -9 21.5 -9t21.5 9l141 141q9 9 9 21.5t-9 21.5l-120 120l120 120q9 9 9 21.5t-9 21.5l-141 141q-9 9 -21.5 9z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM546 623l-84 85q-7 7 -17.5 7t-18.5 -7l-139 -139q-7 -8 -7 -18t7 -18 l242 -241q7 -8 17.5 -8t17.5 8l375 375q7 7 7 17.5t-7 18.5l-139 139q-7 7 -17.5 7t-17.5 -7z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM588 941q-29 0 -59 -5.5t-63 -20.5t-58 -38.5t-41.5 -63t-16.5 -89.5 q0 -25 20 -25h131q30 -5 35 11q6 20 20.5 28t45.5 8q20 0 31.5 -10.5t11.5 -28.5q0 -23 -7 -34t-26 -18q-1 0 -13.5 -4t-19.5 -7.5t-20 -10.5t-22 -17t-18.5 -24t-15.5 -35t-8 -46q-1 -8 5.5 -16.5t20.5 -8.5h173q7 0 22 8t35 28t37.5 48t29.5 74t12 100q0 47 -17 83 t-42.5 57t-59.5 34.5t-64 18t-59 4.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM675 1000h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5 t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5zM675 700h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h75v-200h-75q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h350q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5 t-17.5 7.5h-75v275q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M525 1200h150q10 0 17.5 -7.5t7.5 -17.5v-194q103 -27 178.5 -102.5t102.5 -178.5h194q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-194q-27 -103 -102.5 -178.5t-178.5 -102.5v-194q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v194 q-103 27 -178.5 102.5t-102.5 178.5h-194q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h194q27 103 102.5 178.5t178.5 102.5v194q0 10 7.5 17.5t17.5 7.5zM700 893v-168q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v168q-68 -23 -119 -74 t-74 -119h168q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-168q23 -68 74 -119t119 -74v168q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-168q68 23 119 74t74 119h-168q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h168 q-23 68 -74 119t-119 74z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM759 823l64 -64q7 -7 7 -17.5t-7 -17.5l-124 -124l124 -124q7 -7 7 -17.5t-7 -17.5l-64 -64q-7 -7 -17.5 -7t-17.5 7l-124 124l-124 -124q-7 -7 -17.5 -7t-17.5 7l-64 64 q-7 7 -7 17.5t7 17.5l124 124l-124 124q-7 7 -7 17.5t7 17.5l64 64q7 7 17.5 7t17.5 -7l124 -124l124 124q7 7 17.5 7t17.5 -7z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM782 788l106 -106q7 -7 7 -17.5t-7 -17.5l-320 -321q-8 -7 -18 -7t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l197 197q7 7 17.5 7t17.5 -7z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z" /> +<glyph unicode="" d="M39 582l522 427q16 13 27.5 8t11.5 -26v-291h550q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-550v-291q0 -21 -11.5 -26t-27.5 8l-522 427q-16 13 -16 32t16 32z" /> +<glyph unicode="" d="M639 1009l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291h-550q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h550v291q0 21 11.5 26t27.5 -8z" /> +<glyph unicode="" d="M682 1161l427 -522q13 -16 8 -27.5t-26 -11.5h-291v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v550h-291q-21 0 -26 11.5t8 27.5l427 522q13 16 32 16t32 -16z" /> +<glyph unicode="" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-550h291q21 0 26 -11.5t-8 -27.5l-427 -522q-13 -16 -32 -16t-32 16l-427 522q-13 16 -8 27.5t26 11.5h291v550q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M639 1109l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291q-94 -2 -182 -20t-170.5 -52t-147 -92.5t-100.5 -135.5q5 105 27 193.5t67.5 167t113 135t167 91.5t225.5 42v262q0 21 11.5 26t27.5 -8z" /> +<glyph unicode="" d="M850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5zM350 0h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249 q8 7 18 7t18 -7l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5z" /> +<glyph unicode="" d="M1014 1120l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249q8 7 18 7t18 -7zM250 600h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM704 900h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5 t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M260 1200q9 0 19 -2t15 -4l5 -2q22 -10 44 -23l196 -118q21 -13 36 -24q29 -21 37 -12q11 13 49 35l196 118q22 13 45 23q17 7 38 7q23 0 47 -16.5t37 -33.5l13 -16q14 -21 18 -45l25 -123l8 -44q1 -9 8.5 -14.5t17.5 -5.5h61q10 0 17.5 -7.5t7.5 -17.5v-50 q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 -7.5t-7.5 -17.5v-175h-400v300h-200v-300h-400v175q0 10 -7.5 17.5t-17.5 7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5h61q11 0 18 3t7 8q0 4 9 52l25 128q5 25 19 45q2 3 5 7t13.5 15t21.5 19.5t26.5 15.5 t29.5 7zM915 1079l-166 -162q-7 -7 -5 -12t12 -5h219q10 0 15 7t2 17l-51 149q-3 10 -11 12t-15 -6zM463 917l-177 157q-8 7 -16 5t-11 -12l-51 -143q-3 -10 2 -17t15 -7h231q11 0 12.5 5t-5.5 12zM500 0h-375q-10 0 -17.5 7.5t-7.5 17.5v375h400v-400zM1100 400v-375 q0 -10 -7.5 -17.5t-17.5 -7.5h-375v400h400z" /> +<glyph unicode="" d="M1165 1190q8 3 21 -6.5t13 -17.5q-2 -178 -24.5 -323.5t-55.5 -245.5t-87 -174.5t-102.5 -118.5t-118 -68.5t-118.5 -33t-120 -4.5t-105 9.5t-90 16.5q-61 12 -78 11q-4 1 -12.5 0t-34 -14.5t-52.5 -40.5l-153 -153q-26 -24 -37 -14.5t-11 43.5q0 64 42 102q8 8 50.5 45 t66.5 58q19 17 35 47t13 61q-9 55 -10 102.5t7 111t37 130t78 129.5q39 51 80 88t89.5 63.5t94.5 45t113.5 36t129 31t157.5 37t182 47.5zM1116 1098q-8 9 -22.5 -3t-45.5 -50q-38 -47 -119 -103.5t-142 -89.5l-62 -33q-56 -30 -102 -57t-104 -68t-102.5 -80.5t-85.5 -91 t-64 -104.5q-24 -56 -31 -86t2 -32t31.5 17.5t55.5 59.5q25 30 94 75.5t125.5 77.5t147.5 81q70 37 118.5 69t102 79.5t99 111t86.5 148.5q22 50 24 60t-6 19z" /> +<glyph unicode="" d="M653 1231q-39 -67 -54.5 -131t-10.5 -114.5t24.5 -96.5t47.5 -80t63.5 -62.5t68.5 -46.5t65 -30q-4 7 -17.5 35t-18.5 39.5t-17 39.5t-17 43t-13 42t-9.5 44.5t-2 42t4 43t13.5 39t23 38.5q96 -42 165 -107.5t105 -138t52 -156t13 -159t-19 -149.5q-13 -55 -44 -106.5 t-68 -87t-78.5 -64.5t-72.5 -45t-53 -22q-72 -22 -127 -11q-31 6 -13 19q6 3 17 7q13 5 32.5 21t41 44t38.5 63.5t21.5 81.5t-6.5 94.5t-50 107t-104 115.5q10 -104 -0.5 -189t-37 -140.5t-65 -93t-84 -52t-93.5 -11t-95 24.5q-80 36 -131.5 114t-53.5 171q-2 23 0 49.5 t4.5 52.5t13.5 56t27.5 60t46 64.5t69.5 68.5q-8 -53 -5 -102.5t17.5 -90t34 -68.5t44.5 -39t49 -2q31 13 38.5 36t-4.5 55t-29 64.5t-36 75t-26 75.5q-15 85 2 161.5t53.5 128.5t85.5 92.5t93.5 61t81.5 25.5z" /> +<glyph unicode="" d="M600 1094q82 0 160.5 -22.5t140 -59t116.5 -82.5t94.5 -95t68 -95t42.5 -82.5t14 -57.5t-14 -57.5t-43 -82.5t-68.5 -95t-94.5 -95t-116.5 -82.5t-140 -59t-159.5 -22.5t-159.5 22.5t-140 59t-116.5 82.5t-94.5 95t-68.5 95t-43 82.5t-14 57.5t14 57.5t42.5 82.5t68 95 t94.5 95t116.5 82.5t140 59t160.5 22.5zM888 829q-15 15 -18 12t5 -22q25 -57 25 -119q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 59 23 114q8 19 4.5 22t-17.5 -12q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q22 -36 47 -71t70 -82t92.5 -81t113 -58.5t133.5 -24.5 t133.5 24t113 58.5t92.5 81.5t70 81.5t47 70.5q11 18 9 42.5t-14 41.5q-90 117 -163 189zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44 -89 117q-11 18 -28 20t-32 -12z" /> +<glyph unicode="" d="M592 0h-148l31 120q-91 20 -175.5 68.5t-143.5 106.5t-103.5 119t-66.5 110t-22 76q0 21 14 57.5t42.5 82.5t68 95t94.5 95t116.5 82.5t140 59t160.5 22.5q61 0 126 -15l32 121h148zM944 770l47 181q108 -85 176.5 -192t68.5 -159q0 -26 -19.5 -71t-59.5 -102t-93 -112 t-129 -104.5t-158 -75.5l46 173q77 49 136 117t97 131q11 18 9 42.5t-14 41.5q-54 70 -107 130zM310 824q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q18 -30 39 -60t57 -70.5t74 -73t90 -61t105 -41.5l41 154q-107 18 -178.5 101.5t-71.5 193.5q0 59 23 114q8 19 4.5 22 t-17.5 -12zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l12 11l22 86l-3 4q-44 44 -89 117q-11 18 -28 20t-32 -12z" /> +<glyph unicode="" d="M-90 100l642 1066q20 31 48 28.5t48 -35.5l642 -1056q21 -32 7.5 -67.5t-50.5 -35.5h-1294q-37 0 -50.5 34t7.5 66zM155 200h345v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h345l-445 723zM496 700h208q20 0 32 -14.5t8 -34.5l-58 -252 q-4 -20 -21.5 -34.5t-37.5 -14.5h-54q-20 0 -37.5 14.5t-21.5 34.5l-58 252q-4 20 8 34.5t32 14.5z" /> +<glyph unicode="" d="M650 1200q62 0 106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -93 100 -113v-64q0 -21 -13 -29t-32 1l-205 128l-205 -128q-19 -9 -32 -1t-13 29v64q0 20 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41 q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44z" /> +<glyph unicode="" d="M850 1200h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-150h-1100v150q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-50h500v50q0 21 14.5 35.5t35.5 14.5zM1100 800v-750q0 -21 -14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v750h1100zM100 600v-100h100v100h-100zM300 600v-100h100v100h-100zM500 600v-100h100v100h-100zM700 600v-100h100v100h-100zM900 600v-100h100v100h-100zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400 v-100h100v100h-100zM700 400v-100h100v100h-100zM900 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100zM500 200v-100h100v100h-100zM700 200v-100h100v100h-100zM900 200v-100h100v100h-100z" /> +<glyph unicode="" d="M1135 1165l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-159l-600 -600h-291q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h209l600 600h241v150q0 21 10.5 25t24.5 -10zM522 819l-141 -141l-122 122h-209q-21 0 -35.5 14.5 t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h291zM1135 565l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-241l-181 181l141 141l122 -122h159v150q0 21 10.5 25t24.5 -10z" /> +<glyph unicode="" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" /> +<glyph unicode="" d="M150 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM850 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM1100 800v-300q0 -41 -3 -77.5t-15 -89.5t-32 -96t-58 -89t-89 -77t-129 -51t-174 -20t-174 20 t-129 51t-89 77t-58 89t-32 96t-15 89.5t-3 77.5v300h300v-250v-27v-42.5t1.5 -41t5 -38t10 -35t16.5 -30t25.5 -24.5t35 -19t46.5 -12t60 -4t60 4.5t46.5 12.5t35 19.5t25 25.5t17 30.5t10 35t5 38t2 40.5t-0.5 42v25v250h300z" /> +<glyph unicode="" d="M1100 411l-198 -199l-353 353l-353 -353l-197 199l551 551z" /> +<glyph unicode="" d="M1101 789l-550 -551l-551 551l198 199l353 -353l353 353z" /> +<glyph unicode="" d="M404 1000h746q21 0 35.5 -14.5t14.5 -35.5v-551h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v401h-381zM135 984l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-400h385l215 -200h-750q-21 0 -35.5 14.5 t-14.5 35.5v550h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" /> +<glyph unicode="" d="M56 1200h94q17 0 31 -11t18 -27l38 -162h896q24 0 39 -18.5t10 -42.5l-100 -475q-5 -21 -27 -42.5t-55 -21.5h-633l48 -200h535q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-50q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-300v-50 q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-31q-18 0 -32.5 10t-20.5 19l-5 10l-201 961h-54q-20 0 -35 14.5t-15 35.5t15 35.5t35 14.5z" /> +<glyph unicode="" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" /> +<glyph unicode="" d="M200 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q42 0 71 -29.5t29 -70.5h500v-200h-1000zM1500 700l-300 -700h-1200l300 700h1200z" /> +<glyph unicode="" d="M635 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-601h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v601h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" /> +<glyph unicode="" d="M936 864l249 -229q14 -15 14 -35.5t-14 -35.5l-249 -229q-15 -15 -25.5 -10.5t-10.5 24.5v151h-600v-151q0 -20 -10.5 -24.5t-25.5 10.5l-249 229q-14 15 -14 35.5t14 35.5l249 229q15 15 25.5 10.5t10.5 -25.5v-149h600v149q0 21 10.5 25.5t25.5 -10.5z" /> +<glyph unicode="" d="M1169 400l-172 732q-5 23 -23 45.5t-38 22.5h-672q-20 0 -38 -20t-23 -41l-172 -739h1138zM1100 300h-1000q-41 0 -70.5 -29.5t-29.5 -70.5v-100q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v100q0 41 -29.5 70.5t-70.5 29.5zM800 100v100h100v-100h-100 zM1000 100v100h100v-100h-100z" /> +<glyph unicode="" d="M1150 1100q21 0 35.5 -14.5t14.5 -35.5v-850q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v850q0 21 14.5 35.5t35.5 14.5zM1000 200l-675 200h-38l47 -276q3 -16 -5.5 -20t-29.5 -4h-7h-84q-20 0 -34.5 14t-18.5 35q-55 337 -55 351v250v6q0 16 1 23.5t6.5 14 t17.5 6.5h200l675 250v-850zM0 750v-250q-4 0 -11 0.5t-24 6t-30 15t-24 30t-11 48.5v50q0 26 10.5 46t25 30t29 16t25.5 7z" /> +<glyph unicode="" d="M553 1200h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q19 0 33 -14.5t14 -35t-13 -40.5t-31 -27q-8 -4 -23 -9.5t-65 -19.5t-103 -25t-132.5 -20t-158.5 -9q-57 0 -115 5t-104 12t-88.5 15.5t-73.5 17.5t-54.5 16t-35.5 12l-11 4 q-18 8 -31 28t-13 40.5t14 35t33 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3.5 32t28.5 13zM498 110q50 -6 102 -6q53 0 102 6q-12 -49 -39.5 -79.5t-62.5 -30.5t-63 30.5t-39 79.5z" /> +<glyph unicode="" d="M800 946l224 78l-78 -224l234 -45l-180 -155l180 -155l-234 -45l78 -224l-224 78l-45 -234l-155 180l-155 -180l-45 234l-224 -78l78 224l-234 45l180 155l-180 155l234 45l-78 224l224 -78l45 234l155 -180l155 180z" /> +<glyph unicode="" d="M650 1200h50q40 0 70 -40.5t30 -84.5v-150l-28 -125h328q40 0 70 -40.5t30 -84.5v-100q0 -45 -29 -74l-238 -344q-16 -24 -38 -40.5t-45 -16.5h-250q-7 0 -42 25t-66 50l-31 25h-61q-45 0 -72.5 18t-27.5 57v400q0 36 20 63l145 196l96 198q13 28 37.5 48t51.5 20z M650 1100l-100 -212l-150 -213v-375h100l136 -100h214l250 375v125h-450l50 225v175h-50zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1100h250q23 0 45 -16.5t38 -40.5l238 -344q29 -29 29 -74v-100q0 -44 -30 -84.5t-70 -40.5h-328q28 -118 28 -125v-150q0 -44 -30 -84.5t-70 -40.5h-50q-27 0 -51.5 20t-37.5 48l-96 198l-145 196q-20 27 -20 63v400q0 39 27.5 57t72.5 18h61q124 100 139 100z M50 1000h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM636 1000l-136 -100h-100v-375l150 -213l100 -212h50v175l-50 225h450v125l-250 375h-214z" /> +<glyph unicode="" d="M356 873l363 230q31 16 53 -6l110 -112q13 -13 13.5 -32t-11.5 -34l-84 -121h302q84 0 138 -38t54 -110t-55 -111t-139 -39h-106l-131 -339q-6 -21 -19.5 -41t-28.5 -20h-342q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM400 792v-503l100 -89h293l131 339 q6 21 19.5 41t28.5 20h203q21 0 30.5 25t0.5 50t-31 25h-456h-7h-6h-5.5t-6 0.5t-5 1.5t-5 2t-4 2.5t-4 4t-2.5 4.5q-12 25 5 47l146 183l-86 83zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500 q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M475 1103l366 -230q2 -1 6 -3.5t14 -10.5t18 -16.5t14.5 -20t6.5 -22.5v-525q0 -13 -86 -94t-93 -81h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-85 0 -139.5 39t-54.5 111t54 110t138 38h302l-85 121q-11 15 -10.5 34t13.5 32l110 112q22 22 53 6zM370 945l146 -183 q17 -22 5 -47q-2 -2 -3.5 -4.5t-4 -4t-4 -2.5t-5 -2t-5 -1.5t-6 -0.5h-6h-6.5h-6h-475v-100h221q15 0 29 -20t20 -41l130 -339h294l106 89v503l-342 236zM1050 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5 v500q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M550 1294q72 0 111 -55t39 -139v-106l339 -131q21 -6 41 -19.5t20 -28.5v-342q0 -7 -81 -90t-94 -83h-525q-17 0 -35.5 14t-28.5 28l-9 14l-230 363q-16 31 6 53l112 110q13 13 32 13.5t34 -11.5l121 -84v302q0 84 38 138t110 54zM600 972v203q0 21 -25 30.5t-50 0.5 t-25 -31v-456v-7v-6v-5.5t-0.5 -6t-1.5 -5t-2 -5t-2.5 -4t-4 -4t-4.5 -2.5q-25 -12 -47 5l-183 146l-83 -86l236 -339h503l89 100v293l-339 131q-21 6 -41 19.5t-20 28.5zM450 200h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M350 1100h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5zM600 306v-106q0 -84 -39 -139t-111 -55t-110 54t-38 138v302l-121 -84q-15 -12 -34 -11.5t-32 13.5l-112 110 q-22 22 -6 53l230 363q1 2 3.5 6t10.5 13.5t16.5 17t20 13.5t22.5 6h525q13 0 94 -83t81 -90v-342q0 -15 -20 -28.5t-41 -19.5zM308 900l-236 -339l83 -86l183 146q22 17 47 5q2 -1 4.5 -2.5t4 -4t2.5 -4t2 -5t1.5 -5t0.5 -6v-5.5v-6v-7v-456q0 -22 25 -31t50 0.5t25 30.5 v203q0 15 20 28.5t41 19.5l339 131v293l-89 100h-503z" /> +<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM914 632l-275 223q-16 13 -27.5 8t-11.5 -26v-137h-275 q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h275v-137q0 -21 11.5 -26t27.5 8l275 223q16 13 16 32t-16 32z" /> +<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM561 855l-275 -223q-16 -13 -16 -32t16 -32l275 -223q16 -13 27.5 -8 t11.5 26v137h275q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5h-275v137q0 21 -11.5 26t-27.5 -8z" /> +<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM855 639l-223 275q-13 16 -32 16t-32 -16l-223 -275q-13 -16 -8 -27.5 t26 -11.5h137v-275q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v275h137q21 0 26 11.5t-8 27.5z" /> +<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM675 900h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-275h-137q-21 0 -26 -11.5 t8 -27.5l223 -275q13 -16 32 -16t32 16l223 275q13 16 8 27.5t-26 11.5h-137v275q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M600 1176q116 0 222.5 -46t184 -123.5t123.5 -184t46 -222.5t-46 -222.5t-123.5 -184t-184 -123.5t-222.5 -46t-222.5 46t-184 123.5t-123.5 184t-46 222.5t46 222.5t123.5 184t184 123.5t222.5 46zM627 1101q-15 -12 -36.5 -20.5t-35.5 -12t-43 -8t-39 -6.5 q-15 -3 -45.5 0t-45.5 -2q-20 -7 -51.5 -26.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79q-9 -34 5 -93t8 -87q0 -9 17 -44.5t16 -59.5q12 0 23 -5t23.5 -15t19.5 -14q16 -8 33 -15t40.5 -15t34.5 -12q21 -9 52.5 -32t60 -38t57.5 -11 q7 -15 -3 -34t-22.5 -40t-9.5 -38q13 -21 23 -34.5t27.5 -27.5t36.5 -18q0 -7 -3.5 -16t-3.5 -14t5 -17q104 -2 221 112q30 29 46.5 47t34.5 49t21 63q-13 8 -37 8.5t-36 7.5q-15 7 -49.5 15t-51.5 19q-18 0 -41 -0.5t-43 -1.5t-42 -6.5t-38 -16.5q-51 -35 -66 -12 q-4 1 -3.5 25.5t0.5 25.5q-6 13 -26.5 17.5t-24.5 6.5q1 15 -0.5 30.5t-7 28t-18.5 11.5t-31 -21q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q7 -12 18 -24t21.5 -20.5t20 -15t15.5 -10.5l5 -3q2 12 7.5 30.5t8 34.5t-0.5 32q-3 18 3.5 29 t18 22.5t15.5 24.5q6 14 10.5 35t8 31t15.5 22.5t34 22.5q-6 18 10 36q8 0 24 -1.5t24.5 -1.5t20 4.5t20.5 15.5q-10 23 -31 42.5t-37.5 29.5t-49 27t-43.5 23q0 1 2 8t3 11.5t1.5 10.5t-1 9.5t-4.5 4.5q31 -13 58.5 -14.5t38.5 2.5l12 5q5 28 -9.5 46t-36.5 24t-50 15 t-41 20q-18 -4 -37 0zM613 994q0 -17 8 -42t17 -45t9 -23q-8 1 -39.5 5.5t-52.5 10t-37 16.5q3 11 16 29.5t16 25.5q10 -10 19 -10t14 6t13.5 14.5t16.5 12.5z" /> +<glyph unicode="" d="M756 1157q164 92 306 -9l-259 -138l145 -232l251 126q6 -89 -34 -156.5t-117 -110.5q-60 -34 -127 -39.5t-126 16.5l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-34 101 5.5 201.5t135.5 154.5z" /> +<glyph unicode="" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " /> +<glyph unicode="" d="M150 1200h900q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM700 500v-300l-200 -200v500l-350 500h900z" /> +<glyph unicode="" d="M500 1200h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5zM500 1100v-100h200v100h-200zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" /> +<glyph unicode="" d="M50 1200h300q21 0 25 -10.5t-10 -24.5l-94 -94l199 -199q7 -8 7 -18t-7 -18l-106 -106q-8 -7 -18 -7t-18 7l-199 199l-94 -94q-14 -14 -24.5 -10t-10.5 25v300q0 21 14.5 35.5t35.5 14.5zM850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-199 -199q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l199 199l-94 94q-14 14 -10 24.5t25 10.5zM364 470l106 -106q7 -8 7 -18t-7 -18l-199 -199l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l199 199 q8 7 18 7t18 -7zM1071 271l94 94q14 14 24.5 10t10.5 -25v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -25 10.5t10 24.5l94 94l-199 199q-7 8 -7 18t7 18l106 106q8 7 18 7t18 -7z" /> +<glyph unicode="" d="M596 1192q121 0 231.5 -47.5t190 -127t127 -190t47.5 -231.5t-47.5 -231.5t-127 -190.5t-190 -127t-231.5 -47t-231.5 47t-190.5 127t-127 190.5t-47 231.5t47 231.5t127 190t190.5 127t231.5 47.5zM596 1010q-112 0 -207.5 -55.5t-151 -151t-55.5 -207.5t55.5 -207.5 t151 -151t207.5 -55.5t207.5 55.5t151 151t55.5 207.5t-55.5 207.5t-151 151t-207.5 55.5zM454.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38.5 -16.5t-38.5 16.5t-16 39t16 38.5t38.5 16zM754.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38 -16.5q-14 0 -29 10l-55 -145 q17 -23 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 23 16 39t38.5 16zM345.5 709q22.5 0 38.5 -16t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16zM854.5 709q22.5 0 38.5 -16 t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16z" /> +<glyph unicode="" d="M546 173l469 470q91 91 99 192q7 98 -52 175.5t-154 94.5q-22 4 -47 4q-34 0 -66.5 -10t-56.5 -23t-55.5 -38t-48 -41.5t-48.5 -47.5q-376 -375 -391 -390q-30 -27 -45 -41.5t-37.5 -41t-32 -46.5t-16 -47.5t-1.5 -56.5q9 -62 53.5 -95t99.5 -33q74 0 125 51l548 548 q36 36 20 75q-7 16 -21.5 26t-32.5 10q-26 0 -50 -23q-13 -12 -39 -38l-341 -338q-15 -15 -35.5 -15.5t-34.5 13.5t-14 34.5t14 34.5q327 333 361 367q35 35 67.5 51.5t78.5 16.5q14 0 29 -1q44 -8 74.5 -35.5t43.5 -68.5q14 -47 2 -96.5t-47 -84.5q-12 -11 -32 -32 t-79.5 -81t-114.5 -115t-124.5 -123.5t-123 -119.5t-96.5 -89t-57 -45q-56 -27 -120 -27q-70 0 -129 32t-93 89q-48 78 -35 173t81 163l511 511q71 72 111 96q91 55 198 55q80 0 152 -33q78 -36 129.5 -103t66.5 -154q17 -93 -11 -183.5t-94 -156.5l-482 -476 q-15 -15 -36 -16t-37 14t-17.5 34t14.5 35z" /> +<glyph unicode="" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104zM896 972q-33 0 -64.5 -19t-56.5 -46t-47.5 -53.5t-43.5 -45.5t-37.5 -19t-36 19t-40 45.5t-43 53.5t-54 46t-65.5 19q-67 0 -122.5 -55.5t-55.5 -132.5q0 -23 13.5 -51t46 -65t57.5 -63t76 -75l22 -22q15 -14 44 -44t50.5 -51t46 -44t41 -35t23 -12 t23.5 12t42.5 36t46 44t52.5 52t44 43q4 4 12 13q43 41 63.5 62t52 55t46 55t26 46t11.5 44q0 79 -53 133.5t-120 54.5z" /> +<glyph unicode="" d="M776.5 1214q93.5 0 159.5 -66l141 -141q66 -66 66 -160q0 -42 -28 -95.5t-62 -87.5l-29 -29q-31 53 -77 99l-18 18l95 95l-247 248l-389 -389l212 -212l-105 -106l-19 18l-141 141q-66 66 -66 159t66 159l283 283q65 66 158.5 66zM600 706l105 105q10 -8 19 -17l141 -141 q66 -66 66 -159t-66 -159l-283 -283q-66 -66 -159 -66t-159 66l-141 141q-66 66 -66 159.5t66 159.5l55 55q29 -55 75 -102l18 -17l-95 -95l247 -248l389 389z" /> +<glyph unicode="" d="M603 1200q85 0 162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5v953q0 21 30 46.5t81 48t129 37.5t163 15zM300 1000v-700h600v700h-600zM600 254q-43 0 -73.5 -30.5t-30.5 -73.5t30.5 -73.5t73.5 -30.5t73.5 30.5 t30.5 73.5t-30.5 73.5t-73.5 30.5z" /> +<glyph unicode="" d="M902 1185l283 -282q15 -15 15 -36t-14.5 -35.5t-35.5 -14.5t-35 15l-36 35l-279 -267v-300l-212 210l-308 -307l-280 -203l203 280l307 308l-210 212h300l267 279l-35 36q-15 14 -15 35t14.5 35.5t35.5 14.5t35 -15z" /> +<glyph unicode="" d="M700 1248v-78q38 -5 72.5 -14.5t75.5 -31.5t71 -53.5t52 -84t24 -118.5h-159q-4 36 -10.5 59t-21 45t-40 35.5t-64.5 20.5v-307l64 -13q34 -7 64 -16.5t70 -32t67.5 -52.5t47.5 -80t20 -112q0 -139 -89 -224t-244 -97v-77h-100v79q-150 16 -237 103q-40 40 -52.5 93.5 t-15.5 139.5h139q5 -77 48.5 -126t117.5 -65v335l-27 8q-46 14 -79 26.5t-72 36t-63 52t-40 72.5t-16 98q0 70 25 126t67.5 92t94.5 57t110 27v77h100zM600 754v274q-29 -4 -50 -11t-42 -21.5t-31.5 -41.5t-10.5 -65q0 -29 7 -50.5t16.5 -34t28.5 -22.5t31.5 -14t37.5 -10 q9 -3 13 -4zM700 547v-310q22 2 42.5 6.5t45 15.5t41.5 27t29 42t12 59.5t-12.5 59.5t-38 44.5t-53 31t-66.5 24.5z" /> +<glyph unicode="" d="M561 1197q84 0 160.5 -40t123.5 -109.5t47 -147.5h-153q0 40 -19.5 71.5t-49.5 48.5t-59.5 26t-55.5 9q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -26 13.5 -63t26.5 -61t37 -66q6 -9 9 -14h241v-100h-197q8 -50 -2.5 -115t-31.5 -95q-45 -62 -99 -112 q34 10 83 17.5t71 7.5q32 1 102 -16t104 -17q83 0 136 30l50 -147q-31 -19 -58 -30.5t-55 -15.5t-42 -4.5t-46 -0.5q-23 0 -76 17t-111 32.5t-96 11.5q-39 -3 -82 -16t-67 -25l-23 -11l-55 145q4 3 16 11t15.5 10.5t13 9t15.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221v100h166q-23 47 -44 104q-7 20 -12 41.5t-6 55.5t6 66.5t29.5 70.5t58.5 71q97 88 263 88z" /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM935 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-900h-200v900h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" /> +<glyph unicode="" d="M1000 700h-100v100h-100v-100h-100v500h300v-500zM400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM801 1100v-200h100v200h-100zM1000 350l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150z " /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 1050l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150zM1000 0h-100v100h-100v-100h-100v500h300v-500zM801 400v-200h100v200h-100z " /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 700h-100v400h-100v100h200v-500zM1100 0h-100v100h-200v400h300v-500zM901 400v-200h100v200h-100z" /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1100 700h-100v100h-200v400h300v-500zM901 1100v-200h100v200h-100zM1000 0h-100v400h-100v100h200v-500z" /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" /> +<glyph unicode="" d="M350 1100h400q162 0 256 -93.5t94 -256.5v-400q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5z" /> +<glyph unicode="" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-163 0 -256.5 92.5t-93.5 257.5v400q0 163 94 256.5t256 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM440 770l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" /> +<glyph unicode="" d="M350 1100h400q163 0 256.5 -94t93.5 -256v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 163 92.5 256.5t257.5 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM350 700h400q21 0 26.5 -12t-6.5 -28l-190 -253q-12 -17 -30 -17t-30 17l-190 253q-12 16 -6.5 28t26.5 12z" /> +<glyph unicode="" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -163 -92.5 -256.5t-257.5 -93.5h-400q-163 0 -256.5 94t-93.5 256v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM580 693l190 -253q12 -16 6.5 -28t-26.5 -12h-400q-21 0 -26.5 12t6.5 28l190 253q12 17 30 17t30 -17z" /> +<glyph unicode="" d="M550 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h450q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-450q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM338 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" /> +<glyph unicode="" d="M793 1182l9 -9q8 -10 5 -27q-3 -11 -79 -225.5t-78 -221.5l300 1q24 0 32.5 -17.5t-5.5 -35.5q-1 0 -133.5 -155t-267 -312.5t-138.5 -162.5q-12 -15 -26 -15h-9l-9 8q-9 11 -4 32q2 9 42 123.5t79 224.5l39 110h-302q-23 0 -31 19q-10 21 6 41q75 86 209.5 237.5 t228 257t98.5 111.5q9 16 25 16h9z" /> +<glyph unicode="" d="M350 1100h400q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-450q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h450q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400 q0 165 92.5 257.5t257.5 92.5zM938 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" /> +<glyph unicode="" d="M750 1200h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -10.5 -25t-24.5 10l-109 109l-312 -312q-15 -15 -35.5 -15t-35.5 15l-141 141q-15 15 -15 35.5t15 35.5l312 312l-109 109q-14 14 -10 24.5t25 10.5zM456 900h-156q-41 0 -70.5 -29.5t-29.5 -70.5v-500 q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v148l200 200v-298q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5h300z" /> +<glyph unicode="" d="M600 1186q119 0 227.5 -46.5t187 -125t125 -187t46.5 -227.5t-46.5 -227.5t-125 -187t-187 -125t-227.5 -46.5t-227.5 46.5t-187 125t-125 187t-46.5 227.5t46.5 227.5t125 187t187 125t227.5 46.5zM600 1022q-115 0 -212 -56.5t-153.5 -153.5t-56.5 -212t56.5 -212 t153.5 -153.5t212 -56.5t212 56.5t153.5 153.5t56.5 212t-56.5 212t-153.5 153.5t-212 56.5zM600 794q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" /> +<glyph unicode="" d="M450 1200h200q21 0 35.5 -14.5t14.5 -35.5v-350h245q20 0 25 -11t-9 -26l-383 -426q-14 -15 -33.5 -15t-32.5 15l-379 426q-13 15 -8.5 26t25.5 11h250v350q0 21 14.5 35.5t35.5 14.5zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" /> +<glyph unicode="" d="M583 1182l378 -435q14 -15 9 -31t-26 -16h-244v-250q0 -20 -17 -35t-39 -15h-200q-20 0 -32 14.5t-12 35.5v250h-250q-20 0 -25.5 16.5t8.5 31.5l383 431q14 16 33.5 17t33.5 -14zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" /> +<glyph unicode="" d="M396 723l369 369q7 7 17.5 7t17.5 -7l139 -139q7 -8 7 -18.5t-7 -17.5l-525 -525q-7 -8 -17.5 -8t-17.5 8l-292 291q-7 8 -7 18t7 18l139 139q8 7 18.5 7t17.5 -7zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50 h-100z" /> +<glyph unicode="" d="M135 1023l142 142q14 14 35 14t35 -14l77 -77l-212 -212l-77 76q-14 15 -14 36t14 35zM655 855l210 210q14 14 24.5 10t10.5 -25l-2 -599q-1 -20 -15.5 -35t-35.5 -15l-597 -1q-21 0 -25 10.5t10 24.5l208 208l-154 155l212 212zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5 v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" /> +<glyph unicode="" d="M350 1200l599 -2q20 -1 35 -15.5t15 -35.5l1 -597q0 -21 -10.5 -25t-24.5 10l-208 208l-155 -154l-212 212l155 154l-210 210q-14 14 -10 24.5t25 10.5zM524 512l-76 -77q-15 -14 -36 -14t-35 14l-142 142q-14 14 -14 35t14 35l77 77zM50 300h1000q21 0 35.5 -14.5 t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" /> +<glyph unicode="" d="M1200 103l-483 276l-314 -399v423h-399l1196 796v-1096zM483 424v-230l683 953z" /> +<glyph unicode="" d="M1100 1000v-850q0 -21 -14.5 -35.5t-35.5 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200z" /> +<glyph unicode="" d="M1100 1000l-2 -149l-299 -299l-95 95q-9 9 -21.5 9t-21.5 -9l-149 -147h-312v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1132 638l106 -106q7 -7 7 -17.5t-7 -17.5l-420 -421q-8 -7 -18 -7 t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l297 297q7 7 17.5 7t17.5 -7z" /> +<glyph unicode="" d="M1100 1000v-269l-103 -103l-134 134q-15 15 -33.5 16.5t-34.5 -12.5l-266 -266h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1202 572l70 -70q15 -15 15 -35.5t-15 -35.5l-131 -131 l131 -131q15 -15 15 -35.5t-15 -35.5l-70 -70q-15 -15 -35.5 -15t-35.5 15l-131 131l-131 -131q-15 -15 -35.5 -15t-35.5 15l-70 70q-15 15 -15 35.5t15 35.5l131 131l-131 131q-15 15 -15 35.5t15 35.5l70 70q15 15 35.5 15t35.5 -15l131 -131l131 131q15 15 35.5 15 t35.5 -15z" /> +<glyph unicode="" d="M1100 1000v-300h-350q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM850 600h100q21 0 35.5 -14.5t14.5 -35.5v-250h150q21 0 25 -10.5t-10 -24.5 l-230 -230q-14 -14 -35 -14t-35 14l-230 230q-14 14 -10 24.5t25 10.5h150v250q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M1100 1000v-400l-165 165q-14 15 -35 15t-35 -15l-263 -265h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM935 565l230 -229q14 -15 10 -25.5t-25 -10.5h-150v-250q0 -20 -14.5 -35 t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35v250h-150q-21 0 -25 10.5t10 25.5l230 229q14 15 35 15t35 -15z" /> +<glyph unicode="" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-150h-1200v150q0 21 14.5 35.5t35.5 14.5zM1200 800v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v550h1200zM100 500v-200h400v200h-400z" /> +<glyph unicode="" d="M935 1165l248 -230q14 -14 14 -35t-14 -35l-248 -230q-14 -14 -24.5 -10t-10.5 25v150h-400v200h400v150q0 21 10.5 25t24.5 -10zM200 800h-50q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v-200zM400 800h-100v200h100v-200zM18 435l247 230 q14 14 24.5 10t10.5 -25v-150h400v-200h-400v-150q0 -21 -10.5 -25t-24.5 10l-247 230q-15 14 -15 35t15 35zM900 300h-100v200h100v-200zM1000 500h51q20 0 34.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-34.5 -14.5h-51v200z" /> +<glyph unicode="" d="M862 1073l276 116q25 18 43.5 8t18.5 -41v-1106q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v397q-4 1 -11 5t-24 17.5t-30 29t-24 42t-11 56.5v359q0 31 18.5 65t43.5 52zM550 1200q22 0 34.5 -12.5t14.5 -24.5l1 -13v-450q0 -28 -10.5 -59.5 t-25 -56t-29 -45t-25.5 -31.5l-10 -11v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447q-4 4 -11 11.5t-24 30.5t-30 46t-24 55t-11 60v450q0 2 0.5 5.5t4 12t8.5 15t14.5 12t22.5 5.5q20 0 32.5 -12.5t14.5 -24.5l3 -13v-350h100v350v5.5t2.5 12 t7 15t15 12t25.5 5.5q23 0 35.5 -12.5t13.5 -24.5l1 -13v-350h100v350q0 2 0.5 5.5t3 12t7 15t15 12t24.5 5.5z" /> +<glyph unicode="" d="M1200 1100v-56q-4 0 -11 -0.5t-24 -3t-30 -7.5t-24 -15t-11 -24v-888q0 -22 25 -34.5t50 -13.5l25 -2v-56h-400v56q75 0 87.5 6.5t12.5 43.5v394h-500v-394q0 -37 12.5 -43.5t87.5 -6.5v-56h-400v56q4 0 11 0.5t24 3t30 7.5t24 15t11 24v888q0 22 -25 34.5t-50 13.5 l-25 2v56h400v-56q-75 0 -87.5 -6.5t-12.5 -43.5v-394h500v394q0 37 -12.5 43.5t-87.5 6.5v56h400z" /> +<glyph unicode="" d="M675 1000h375q21 0 35.5 -14.5t14.5 -35.5v-150h-105l-295 -98v98l-200 200h-400l100 100h375zM100 900h300q41 0 70.5 -29.5t29.5 -70.5v-500q0 -41 -29.5 -70.5t-70.5 -29.5h-300q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5zM100 800v-200h300v200 h-300zM1100 535l-400 -133v163l400 133v-163zM100 500v-200h300v200h-300zM1100 398v-248q0 -21 -14.5 -35.5t-35.5 -14.5h-375l-100 -100h-375l-100 100h400l200 200h105z" /> +<glyph unicode="" d="M17 1007l162 162q17 17 40 14t37 -22l139 -194q14 -20 11 -44.5t-20 -41.5l-119 -118q102 -142 228 -268t267 -227l119 118q17 17 42.5 19t44.5 -12l192 -136q19 -14 22.5 -37.5t-13.5 -40.5l-163 -162q-3 -1 -9.5 -1t-29.5 2t-47.5 6t-62.5 14.5t-77.5 26.5t-90 42.5 t-101.5 60t-111 83t-119 108.5q-74 74 -133.5 150.5t-94.5 138.5t-60 119.5t-34.5 100t-15 74.5t-4.5 48z" /> +<glyph unicode="" d="M600 1100q92 0 175 -10.5t141.5 -27t108.5 -36.5t81.5 -40t53.5 -37t31 -27l9 -10v-200q0 -21 -14.5 -33t-34.5 -9l-202 34q-20 3 -34.5 20t-14.5 38v146q-141 24 -300 24t-300 -24v-146q0 -21 -14.5 -38t-34.5 -20l-202 -34q-20 -3 -34.5 9t-14.5 33v200q3 4 9.5 10.5 t31 26t54 37.5t80.5 39.5t109 37.5t141 26.5t175 10.5zM600 795q56 0 97 -9.5t60 -23.5t30 -28t12 -24l1 -10v-50l365 -303q14 -15 24.5 -40t10.5 -45v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45t24.5 40l365 303v50 q0 4 1 10.5t12 23t30 29t60 22.5t97 10z" /> +<glyph unicode="" d="M1100 700l-200 -200h-600l-200 200v500h200v-200h200v200h200v-200h200v200h200v-500zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5 t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M700 1100h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-1000h300v1000q0 41 -29.5 70.5t-70.5 29.5zM1100 800h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-700h300v700q0 41 -29.5 70.5t-70.5 29.5zM400 0h-300v400q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-400z " /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 300h-100v200h-100v-200h-100v500h100v-200h100v200h100v-500zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-300h200v-100h-300v500h300v-100zM900 700h-200v-300h200v-100h-300v500h300v-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 400l-300 150l300 150v-300zM900 550l-300 -150v300z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM900 300h-700v500h700v-500zM800 700h-130q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300zM300 700v-300 h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 300h-100v400h-100v100h200v-500z M700 300h-100v100h100v-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM300 700h200v-400h-300v500h100v-100zM900 300h-100v400h-100v100h200v-500zM300 600v-200h100v200h-100z M700 300h-100v100h100v-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 500l-199 -200h-100v50l199 200v150h-200v100h300v-300zM900 300h-100v400h-100v100h200v-500zM701 300h-100 v100h100v-100z" /> +<glyph unicode="" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700h-300v-200h300v-100h-300l-100 100v200l100 100h300v-100z" /> +<glyph unicode="" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700v-100l-50 -50l100 -100v-50h-100l-100 100h-150v-100h-100v400h300zM500 700v-100h200v100h-200z" /> +<glyph unicode="" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -207t-85 -207t-205 -86.5h-128v250q0 21 -14.5 35.5t-35.5 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-250h-222q-80 0 -136 57.5t-56 136.5q0 69 43 122.5t108 67.5q-2 19 -2 37q0 100 49 185 t134 134t185 49zM525 500h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -244q-13 -16 -32 -16t-32 16l-223 244q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M502 1089q110 0 201 -59.5t135 -156.5q43 15 89 15q121 0 206 -86.5t86 -206.5q0 -99 -60 -181t-150 -110l-378 360q-13 16 -31.5 16t-31.5 -16l-381 -365h-9q-79 0 -135.5 57.5t-56.5 136.5q0 69 43 122.5t108 67.5q-2 19 -2 38q0 100 49 184.5t133.5 134t184.5 49.5z M632 467l223 -228q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5q199 204 223 228q19 19 31.5 19t32.5 -19z" /> +<glyph unicode="" d="M700 100v100h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-100h-50q-21 0 -35.5 -14.5t-14.5 -35.5v-50h400v50q0 21 -14.5 35.5t-35.5 14.5h-50z" /> +<glyph unicode="" d="M600 1179q94 0 167.5 -56.5t99.5 -145.5q89 -6 150.5 -71.5t61.5 -155.5q0 -61 -29.5 -112.5t-79.5 -82.5q9 -29 9 -55q0 -74 -52.5 -126.5t-126.5 -52.5q-55 0 -100 30v-251q21 0 35.5 -14.5t14.5 -35.5v-50h-300v50q0 21 14.5 35.5t35.5 14.5v251q-45 -30 -100 -30 q-74 0 -126.5 52.5t-52.5 126.5q0 18 4 38q-47 21 -75.5 65t-28.5 97q0 74 52.5 126.5t126.5 52.5q5 0 23 -2q0 2 -1 10t-1 13q0 116 81.5 197.5t197.5 81.5z" /> +<glyph unicode="" d="M1010 1010q111 -111 150.5 -260.5t0 -299t-150.5 -260.5q-83 -83 -191.5 -126.5t-218.5 -43.5t-218.5 43.5t-191.5 126.5q-111 111 -150.5 260.5t0 299t150.5 260.5q83 83 191.5 126.5t218.5 43.5t218.5 -43.5t191.5 -126.5zM476 1065q-4 0 -8 -1q-121 -34 -209.5 -122.5 t-122.5 -209.5q-4 -12 2.5 -23t18.5 -14l36 -9q3 -1 7 -1q23 0 29 22q27 96 98 166q70 71 166 98q11 3 17.5 13.5t3.5 22.5l-9 35q-3 13 -14 19q-7 4 -15 4zM512 920q-4 0 -9 -2q-80 -24 -138.5 -82.5t-82.5 -138.5q-4 -13 2 -24t19 -14l34 -9q4 -1 8 -1q22 0 28 21 q18 58 58.5 98.5t97.5 58.5q12 3 18 13.5t3 21.5l-9 35q-3 12 -14 19q-7 4 -15 4zM719.5 719.5q-49.5 49.5 -119.5 49.5t-119.5 -49.5t-49.5 -119.5t49.5 -119.5t119.5 -49.5t119.5 49.5t49.5 119.5t-49.5 119.5zM855 551q-22 0 -28 -21q-18 -58 -58.5 -98.5t-98.5 -57.5 q-11 -4 -17 -14.5t-3 -21.5l9 -35q3 -12 14 -19q7 -4 15 -4q4 0 9 2q80 24 138.5 82.5t82.5 138.5q4 13 -2.5 24t-18.5 14l-34 9q-4 1 -8 1zM1000 515q-23 0 -29 -22q-27 -96 -98 -166q-70 -71 -166 -98q-11 -3 -17.5 -13.5t-3.5 -22.5l9 -35q3 -13 14 -19q7 -4 15 -4 q4 0 8 1q121 34 209.5 122.5t122.5 209.5q4 12 -2.5 23t-18.5 14l-36 9q-3 1 -7 1z" /> +<glyph unicode="" d="M700 800h300v-380h-180v200h-340v-200h-380v755q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM700 300h162l-212 -212l-212 212h162v200h100v-200zM520 0h-395q-10 0 -17.5 7.5t-7.5 17.5v395zM1000 220v-195q0 -10 -7.5 -17.5t-17.5 -7.5h-195z" /> +<glyph unicode="" d="M700 800h300v-520l-350 350l-550 -550v1095q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM862 200h-162v-200h-100v200h-162l212 212zM480 0h-355q-10 0 -17.5 7.5t-7.5 17.5v55h380v-80zM1000 80v-55q0 -10 -7.5 -17.5t-17.5 -7.5h-155v80h180z" /> +<glyph unicode="" d="M1162 800h-162v-200h100l100 -100h-300v300h-162l212 212zM200 800h200q27 0 40 -2t29.5 -10.5t23.5 -30t7 -57.5h300v-100h-600l-200 -350v450h100q0 36 7 57.5t23.5 30t29.5 10.5t40 2zM800 400h240l-240 -400h-800l300 500h500v-100z" /> +<glyph unicode="" d="M650 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM1000 850v150q41 0 70.5 -29.5t29.5 -70.5v-800 q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-1 0 -20 4l246 246l-326 326v324q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM412 250l-212 -212v162h-200v100h200v162z" /> +<glyph unicode="" d="M450 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM800 850v150q41 0 70.5 -29.5t29.5 -70.5v-500 h-200v-300h200q0 -36 -7 -57.5t-23.5 -30t-29.5 -10.5t-40 -2h-600q-41 0 -70.5 29.5t-29.5 70.5v800q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM1212 250l-212 -212v162h-200v100h200v162z" /> +<glyph unicode="" d="M658 1197l637 -1104q23 -38 7 -65.5t-60 -27.5h-1276q-44 0 -60 27.5t7 65.5l637 1104q22 39 54 39t54 -39zM704 800h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM500 300v-100h200 v100h-200z" /> +<glyph unicode="" d="M425 1100h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM825 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM25 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5zM425 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5 v150q0 10 7.5 17.5t17.5 7.5zM25 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M700 1200h100v-200h-100v-100h350q62 0 86.5 -39.5t-3.5 -94.5l-66 -132q-41 -83 -81 -134h-772q-40 51 -81 134l-66 132q-28 55 -3.5 94.5t86.5 39.5h350v100h-100v200h100v100h200v-100zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100 h-950l138 100h-13q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1300q40 0 68.5 -29.5t28.5 -70.5h-194q0 41 28.5 70.5t68.5 29.5zM443 1100h314q18 -37 18 -75q0 -8 -3 -25h328q41 0 44.5 -16.5t-30.5 -38.5l-175 -145h-678l-178 145q-34 22 -29 38.5t46 16.5h328q-3 17 -3 25q0 38 18 75zM250 700h700q21 0 35.5 -14.5 t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-150v-200l275 -200h-950l275 200v200h-150q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1181q75 0 128 -53t53 -128t-53 -128t-128 -53t-128 53t-53 128t53 128t128 53zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13 l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1300q47 0 92.5 -53.5t71 -123t25.5 -123.5q0 -78 -55.5 -133.5t-133.5 -55.5t-133.5 55.5t-55.5 133.5q0 62 34 143l144 -143l111 111l-163 163q34 26 63 26zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45 zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1200l300 -161v-139h-300q0 -57 18.5 -108t50 -91.5t63 -72t70 -67.5t57.5 -61h-530q-60 83 -90.5 177.5t-30.5 178.5t33 164.5t87.5 139.5t126 96.5t145.5 41.5v-98zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100 h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1300q41 0 70.5 -29.5t29.5 -70.5v-78q46 -26 73 -72t27 -100v-50h-400v50q0 54 27 100t73 72v78q0 41 29.5 70.5t70.5 29.5zM400 800h400q54 0 100 -27t72 -73h-172v-100h200v-100h-200v-100h200v-100h-200v-100h200q0 -83 -58.5 -141.5t-141.5 -58.5h-400 q-83 0 -141.5 58.5t-58.5 141.5v400q0 83 58.5 141.5t141.5 58.5z" /> +<glyph unicode="" d="M150 1100h900q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM125 400h950q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-283l224 -224q13 -13 13 -31.5t-13 -32 t-31.5 -13.5t-31.5 13l-88 88h-524l-87 -88q-13 -13 -32 -13t-32 13.5t-13 32t13 31.5l224 224h-289q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM541 300l-100 -100h324l-100 100h-124z" /> +<glyph unicode="" d="M200 1100h800q83 0 141.5 -58.5t58.5 -141.5v-200h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100v200q0 83 58.5 141.5t141.5 58.5zM100 600h1000q41 0 70.5 -29.5 t29.5 -70.5v-300h-1200v300q0 41 29.5 70.5t70.5 29.5zM300 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200zM1100 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200z" /> +<glyph unicode="" d="M480 1165l682 -683q31 -31 31 -75.5t-31 -75.5l-131 -131h-481l-517 518q-32 31 -32 75.5t32 75.5l295 296q31 31 75.5 31t76.5 -31zM108 794l342 -342l303 304l-341 341zM250 100h800q21 0 35.5 -14.5t14.5 -35.5v-50h-900v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M1057 647l-189 506q-8 19 -27.5 33t-40.5 14h-400q-21 0 -40.5 -14t-27.5 -33l-189 -506q-8 -19 1.5 -33t30.5 -14h625v-150q0 -21 14.5 -35.5t35.5 -14.5t35.5 14.5t14.5 35.5v150h125q21 0 30.5 14t1.5 33zM897 0h-595v50q0 21 14.5 35.5t35.5 14.5h50v50 q0 21 14.5 35.5t35.5 14.5h48v300h200v-300h47q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-50z" /> +<glyph unicode="" d="M900 800h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-375v591l-300 300v84q0 10 7.5 17.5t17.5 7.5h375v-400zM1200 900h-200v200zM400 600h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-650q-10 0 -17.5 7.5t-7.5 17.5v950q0 10 7.5 17.5t17.5 7.5h375v-400zM700 700h-200v200z " /> +<glyph unicode="" d="M484 1095h195q75 0 146 -32.5t124 -86t89.5 -122.5t48.5 -142q18 -14 35 -20q31 -10 64.5 6.5t43.5 48.5q10 34 -15 71q-19 27 -9 43q5 8 12.5 11t19 -1t23.5 -16q41 -44 39 -105q-3 -63 -46 -106.5t-104 -43.5h-62q-7 -55 -35 -117t-56 -100l-39 -234q-3 -20 -20 -34.5 t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l12 70q-49 -14 -91 -14h-195q-24 0 -65 8l-11 -64q-3 -20 -20 -34.5t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l26 157q-84 74 -128 175l-159 53q-19 7 -33 26t-14 40v50q0 21 14.5 35.5t35.5 14.5h124q11 87 56 166l-111 95 q-16 14 -12.5 23.5t24.5 9.5h203q116 101 250 101zM675 1000h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h250q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M641 900l423 247q19 8 42 2.5t37 -21.5l32 -38q14 -15 12.5 -36t-17.5 -34l-139 -120h-390zM50 1100h106q67 0 103 -17t66 -71l102 -212h823q21 0 35.5 -14.5t14.5 -35.5v-50q0 -21 -14 -40t-33 -26l-737 -132q-23 -4 -40 6t-26 25q-42 67 -100 67h-300q-62 0 -106 44 t-44 106v200q0 62 44 106t106 44zM173 928h-80q-19 0 -28 -14t-9 -35v-56q0 -51 42 -51h134q16 0 21.5 8t5.5 24q0 11 -16 45t-27 51q-18 28 -43 28zM550 727q-32 0 -54.5 -22.5t-22.5 -54.5t22.5 -54.5t54.5 -22.5t54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5zM130 389 l152 130q18 19 34 24t31 -3.5t24.5 -17.5t25.5 -28q28 -35 50.5 -51t48.5 -13l63 5l48 -179q13 -61 -3.5 -97.5t-67.5 -79.5l-80 -69q-47 -40 -109 -35.5t-103 51.5l-130 151q-40 47 -35.5 109.5t51.5 102.5zM380 377l-102 -88q-31 -27 2 -65l37 -43q13 -15 27.5 -19.5 t31.5 6.5l61 53q19 16 14 49q-2 20 -12 56t-17 45q-11 12 -19 14t-23 -8z" /> +<glyph unicode="" d="M625 1200h150q10 0 17.5 -7.5t7.5 -17.5v-109q79 -33 131 -87.5t53 -128.5q1 -46 -15 -84.5t-39 -61t-46 -38t-39 -21.5l-17 -6q6 0 15 -1.5t35 -9t50 -17.5t53 -30t50 -45t35.5 -64t14.5 -84q0 -59 -11.5 -105.5t-28.5 -76.5t-44 -51t-49.5 -31.5t-54.5 -16t-49.5 -6.5 t-43.5 -1v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-100v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-175q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v600h-75q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5h175v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h100v75q0 10 7.5 17.5t17.5 7.5zM400 900v-200h263q28 0 48.5 10.5t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-263zM400 500v-200h363q28 0 48.5 10.5 t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-363z" /> +<glyph unicode="" d="M212 1198h780q86 0 147 -61t61 -147v-416q0 -51 -18 -142.5t-36 -157.5l-18 -66q-29 -87 -93.5 -146.5t-146.5 -59.5h-572q-82 0 -147 59t-93 147q-8 28 -20 73t-32 143.5t-20 149.5v416q0 86 61 147t147 61zM600 1045q-70 0 -132.5 -11.5t-105.5 -30.5t-78.5 -41.5 t-57 -45t-36 -41t-20.5 -30.5l-6 -12l156 -243h560l156 243q-2 5 -6 12.5t-20 29.5t-36.5 42t-57 44.5t-79 42t-105 29.5t-132.5 12zM762 703h-157l195 261z" /> +<glyph unicode="" d="M475 1300h150q103 0 189 -86t86 -189v-500q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" /> +<glyph unicode="" d="M475 1300h96q0 -150 89.5 -239.5t239.5 -89.5v-446q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" /> +<glyph unicode="" d="M1294 767l-638 -283l-378 170l-78 -60v-224l100 -150v-199l-150 148l-150 -149v200l100 150v250q0 4 -0.5 10.5t0 9.5t1 8t3 8t6.5 6l47 40l-147 65l642 283zM1000 380l-350 -166l-350 166v147l350 -165l350 165v-147z" /> +<glyph unicode="" d="M250 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM650 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM1050 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" /> +<glyph unicode="" d="M550 1100q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 700q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 300q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" /> +<glyph unicode="" d="M125 1100h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM125 700h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM125 300h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M350 1200h500q162 0 256 -93.5t94 -256.5v-500q0 -165 -93.5 -257.5t-256.5 -92.5h-500q-165 0 -257.5 92.5t-92.5 257.5v500q0 165 92.5 257.5t257.5 92.5zM900 1000h-600q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h600q41 0 70.5 29.5 t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5zM350 900h500q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-500q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 14.5 35.5t35.5 14.5zM400 800v-200h400v200h-400z" /> +<glyph unicode="" d="M150 1100h1000q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M650 1187q87 -67 118.5 -156t0 -178t-118.5 -155q-87 66 -118.5 155t0 178t118.5 156zM300 800q124 0 212 -88t88 -212q-124 0 -212 88t-88 212zM1000 800q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM300 500q124 0 212 -88t88 -212q-124 0 -212 88t-88 212z M1000 500q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM700 199v-144q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v142q40 -4 43 -4q17 0 57 6z" /> +<glyph unicode="" d="M745 878l69 19q25 6 45 -12l298 -295q11 -11 15 -26.5t-2 -30.5q-5 -14 -18 -23.5t-28 -9.5h-8q1 0 1 -13q0 -29 -2 -56t-8.5 -62t-20 -63t-33 -53t-51 -39t-72.5 -14h-146q-184 0 -184 288q0 24 10 47q-20 4 -62 4t-63 -4q11 -24 11 -47q0 -288 -184 -288h-142 q-48 0 -84.5 21t-56 51t-32 71.5t-16 75t-3.5 68.5q0 13 2 13h-7q-15 0 -27.5 9.5t-18.5 23.5q-6 15 -2 30.5t15 25.5l298 296q20 18 46 11l76 -19q20 -5 30.5 -22.5t5.5 -37.5t-22.5 -31t-37.5 -5l-51 12l-182 -193h891l-182 193l-44 -12q-20 -5 -37.5 6t-22.5 31t6 37.5 t31 22.5z" /> +<glyph unicode="" d="M1200 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM500 450h-25q0 15 -4 24.5t-9 14.5t-17 7.5t-20 3t-25 0.5h-100v-425q0 -11 12.5 -17.5t25.5 -7.5h12v-50h-200v50q50 0 50 25v425h-100q-17 0 -25 -0.5t-20 -3t-17 -7.5t-9 -14.5t-4 -24.5h-25v150h500v-150z" /> +<glyph unicode="" d="M1000 300v50q-25 0 -55 32q-14 14 -25 31t-16 27l-4 11l-289 747h-69l-300 -754q-18 -35 -39 -56q-9 -9 -24.5 -18.5t-26.5 -14.5l-11 -5v-50h273v50q-49 0 -78.5 21.5t-11.5 67.5l69 176h293l61 -166q13 -34 -3.5 -66.5t-55.5 -32.5v-50h312zM412 691l134 342l121 -342 h-255zM1100 150v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" /> +<glyph unicode="" d="M50 1200h1100q21 0 35.5 -14.5t14.5 -35.5v-1100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5zM611 1118h-70q-13 0 -18 -12l-299 -753q-17 -32 -35 -51q-18 -18 -56 -34q-12 -5 -12 -18v-50q0 -8 5.5 -14t14.5 -6 h273q8 0 14 6t6 14v50q0 8 -6 14t-14 6q-55 0 -71 23q-10 14 0 39l63 163h266l57 -153q11 -31 -6 -55q-12 -17 -36 -17q-8 0 -14 -6t-6 -14v-50q0 -8 6 -14t14 -6h313q8 0 14 6t6 14v50q0 7 -5.5 13t-13.5 7q-17 0 -42 25q-25 27 -40 63h-1l-288 748q-5 12 -19 12zM639 611 h-197l103 264z" /> +<glyph unicode="" d="M1200 1100h-1200v100h1200v-100zM50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 1000h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM700 900v-300h300v300h-300z" /> +<glyph unicode="" d="M50 1200h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 700h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM700 600v-300h300v300h-300zM1200 0h-1200v100h1200v-100z" /> +<glyph unicode="" d="M50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-350h100v150q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-150h100v-100h-100v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v150h-100v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM700 700v-300h300v300h-300z" /> +<glyph unicode="" d="M100 0h-100v1200h100v-1200zM250 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM300 1000v-300h300v300h-300zM250 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1100h150q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-100h450q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h350v100h-150q-21 0 -35.5 14.5 t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h150v100h100v-100zM400 1000v-300h300v300h-300z" /> +<glyph unicode="" d="M1200 0h-100v1200h100v-1200zM550 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM600 1000v-300h300v300h-300zM50 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M865 565l-494 -494q-23 -23 -41 -23q-14 0 -22 13.5t-8 38.5v1000q0 25 8 38.5t22 13.5q18 0 41 -23l494 -494q14 -14 14 -35t-14 -35z" /> +<glyph unicode="" d="M335 635l494 494q29 29 50 20.5t21 -49.5v-1000q0 -41 -21 -49.5t-50 20.5l-494 494q-14 14 -14 35t14 35z" /> +<glyph unicode="" d="M100 900h1000q41 0 49.5 -21t-20.5 -50l-494 -494q-14 -14 -35 -14t-35 14l-494 494q-29 29 -20.5 50t49.5 21z" /> +<glyph unicode="" d="M635 865l494 -494q29 -29 20.5 -50t-49.5 -21h-1000q-41 0 -49.5 21t20.5 50l494 494q14 14 35 14t35 -14z" /> +<glyph unicode="" d="M700 741v-182l-692 -323v221l413 193l-413 193v221zM1200 0h-800v200h800v-200z" /> +<glyph unicode="" d="M1200 900h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300zM0 700h50q0 21 4 37t9.5 26.5t18 17.5t22 11t28.5 5.5t31 2t37 0.5h100v-550q0 -22 -25 -34.5t-50 -13.5l-25 -2v-100h400v100q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v550h100q25 0 37 -0.5t31 -2 t28.5 -5.5t22 -11t18 -17.5t9.5 -26.5t4 -37h50v300h-800v-300z" /> +<glyph unicode="" d="M800 700h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-100v-550q0 -22 25 -34.5t50 -14.5l25 -1v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v550h-100q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h800v-300zM1100 200h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300z" /> +<glyph unicode="" d="M701 1098h160q16 0 21 -11t-7 -23l-464 -464l464 -464q12 -12 7 -23t-21 -11h-160q-13 0 -23 9l-471 471q-7 8 -7 18t7 18l471 471q10 9 23 9z" /> +<glyph unicode="" d="M339 1098h160q13 0 23 -9l471 -471q7 -8 7 -18t-7 -18l-471 -471q-10 -9 -23 -9h-160q-16 0 -21 11t7 23l464 464l-464 464q-12 12 -7 23t21 11z" /> +<glyph unicode="" d="M1087 882q11 -5 11 -21v-160q0 -13 -9 -23l-471 -471q-8 -7 -18 -7t-18 7l-471 471q-9 10 -9 23v160q0 16 11 21t23 -7l464 -464l464 464q12 12 23 7z" /> +<glyph unicode="" d="M618 993l471 -471q9 -10 9 -23v-160q0 -16 -11 -21t-23 7l-464 464l-464 -464q-12 -12 -23 -7t-11 21v160q0 13 9 23l471 471q8 7 18 7t18 -7z" /> +<glyph unicode="" d="M1000 1200q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM450 1000h100q21 0 40 -14t26 -33l79 -194q5 1 16 3q34 6 54 9.5t60 7t65.5 1t61 -10t56.5 -23t42.5 -42t29 -64t5 -92t-19.5 -121.5q-1 -7 -3 -19.5t-11 -50t-20.5 -73t-32.5 -81.5t-46.5 -83t-64 -70 t-82.5 -50q-13 -5 -42 -5t-65.5 2.5t-47.5 2.5q-14 0 -49.5 -3.5t-63 -3.5t-43.5 7q-57 25 -104.5 78.5t-75 111.5t-46.5 112t-26 90l-7 35q-15 63 -18 115t4.5 88.5t26 64t39.5 43.5t52 25.5t58.5 13t62.5 2t59.5 -4.5t55.5 -8l-147 192q-12 18 -5.5 30t27.5 12z" /> +<glyph unicode="🔑" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" /> +<glyph unicode="🚪" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" /> </font> </defs></svg>
\ No newline at end of file diff --git a/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf b/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf Binary files differindex 67fa00b..1413fc6 100644 --- a/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf +++ b/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf diff --git a/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff b/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff Binary files differindex 8c54182..9e61285 100644 --- a/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff +++ b/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff diff --git a/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 b/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 Binary files differnew file mode 100644 index 0000000..64539b5 --- /dev/null +++ b/bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2 diff --git a/bower_components/bootstrap/dist/js/npm.js b/bower_components/bootstrap/dist/js/npm.js new file mode 100644 index 0000000..bf6aa80 --- /dev/null +++ b/bower_components/bootstrap/dist/js/npm.js @@ -0,0 +1,13 @@ +// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. +require('../../js/transition.js') +require('../../js/alert.js') +require('../../js/button.js') +require('../../js/carousel.js') +require('../../js/collapse.js') +require('../../js/dropdown.js') +require('../../js/modal.js') +require('../../js/tooltip.js') +require('../../js/popover.js') +require('../../js/scrollspy.js') +require('../../js/tab.js') +require('../../js/affix.js')
\ No newline at end of file diff --git a/bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot b/bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot Binary files differindex 4a4ca86..b93a495 100644 --- a/bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot +++ b/bower_components/bootstrap/fonts/glyphicons-halflings-regular.eot diff --git a/bower_components/bootstrap/fonts/glyphicons-halflings-regular.svg b/bower_components/bootstrap/fonts/glyphicons-halflings-regular.svg index e3e2dc7..94fb549 100644 --- a/bower_components/bootstrap/fonts/glyphicons-halflings-regular.svg +++ b/bower_components/bootstrap/fonts/glyphicons-halflings-regular.svg @@ -6,224 +6,283 @@ <font id="glyphicons_halflingsregular" horiz-adv-x="1200" > <font-face units-per-em="1200" ascent="960" descent="-240" /> <missing-glyph horiz-adv-x="500" /> -<glyph /> -<glyph /> -<glyph unicode="
" /> +<glyph horiz-adv-x="0" /> +<glyph horiz-adv-x="400" /> <glyph unicode=" " /> -<glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" /> -<glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" /> +<glyph unicode="*" d="M600 1100q15 0 34 -1.5t30 -3.5l11 -1q10 -2 17.5 -10.5t7.5 -18.5v-224l158 158q7 7 18 8t19 -6l106 -106q7 -8 6 -19t-8 -18l-158 -158h224q10 0 18.5 -7.5t10.5 -17.5q6 -41 6 -75q0 -15 -1.5 -34t-3.5 -30l-1 -11q-2 -10 -10.5 -17.5t-18.5 -7.5h-224l158 -158 q7 -7 8 -18t-6 -19l-106 -106q-8 -7 -19 -6t-18 8l-158 158v-224q0 -10 -7.5 -18.5t-17.5 -10.5q-41 -6 -75 -6q-15 0 -34 1.5t-30 3.5l-11 1q-10 2 -17.5 10.5t-7.5 18.5v224l-158 -158q-7 -7 -18 -8t-19 6l-106 106q-7 8 -6 19t8 18l158 158h-224q-10 0 -18.5 7.5 t-10.5 17.5q-6 41 -6 75q0 15 1.5 34t3.5 30l1 11q2 10 10.5 17.5t18.5 7.5h224l-158 158q-7 7 -8 18t6 19l106 106q8 7 19 6t18 -8l158 -158v224q0 10 7.5 18.5t17.5 10.5q41 6 75 6z" /> +<glyph unicode="+" d="M450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-350h350q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-350v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v350h-350q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5 h350v350q0 21 14.5 35.5t35.5 14.5z" /> <glyph unicode=" " /> -<glyph unicode=" " horiz-adv-x="652" /> -<glyph unicode=" " horiz-adv-x="1304" /> -<glyph unicode=" " horiz-adv-x="652" /> -<glyph unicode=" " horiz-adv-x="1304" /> -<glyph unicode=" " horiz-adv-x="434" /> -<glyph unicode=" " horiz-adv-x="326" /> -<glyph unicode=" " horiz-adv-x="217" /> -<glyph unicode=" " horiz-adv-x="217" /> -<glyph unicode=" " horiz-adv-x="163" /> +<glyph unicode="¥" d="M825 1100h250q10 0 12.5 -5t-5.5 -13l-364 -364q-6 -6 -11 -18h268q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-100h275q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-125v-174q0 -11 -7.5 -18.5t-18.5 -7.5h-148q-11 0 -18.5 7.5t-7.5 18.5v174 h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h125v100h-275q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h118q-5 12 -11 18l-364 364q-8 8 -5.5 13t12.5 5h250q25 0 43 -18l164 -164q8 -8 18 -8t18 8l164 164q18 18 43 18z" /> +<glyph unicode=" " horiz-adv-x="650" /> +<glyph unicode=" " horiz-adv-x="1300" /> +<glyph unicode=" " horiz-adv-x="650" /> +<glyph unicode=" " horiz-adv-x="1300" /> +<glyph unicode=" " horiz-adv-x="433" /> +<glyph unicode=" " horiz-adv-x="325" /> +<glyph unicode=" " horiz-adv-x="216" /> +<glyph unicode=" " horiz-adv-x="216" /> +<glyph unicode=" " horiz-adv-x="162" /> <glyph unicode=" " horiz-adv-x="260" /> <glyph unicode=" " horiz-adv-x="72" /> <glyph unicode=" " horiz-adv-x="260" /> -<glyph unicode=" " horiz-adv-x="326" /> -<glyph unicode="€" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" /> -<glyph unicode="−" d="M200 400h900v300h-900v-300z" /> +<glyph unicode=" " horiz-adv-x="325" /> +<glyph unicode="€" d="M744 1198q242 0 354 -189q60 -104 66 -209h-181q0 45 -17.5 82.5t-43.5 61.5t-58 40.5t-60.5 24t-51.5 7.5q-19 0 -40.5 -5.5t-49.5 -20.5t-53 -38t-49 -62.5t-39 -89.5h379l-100 -100h-300q-6 -50 -6 -100h406l-100 -100h-300q9 -74 33 -132t52.5 -91t61.5 -54.5t59 -29 t47 -7.5q22 0 50.5 7.5t60.5 24.5t58 41t43.5 61t17.5 80h174q-30 -171 -128 -278q-107 -117 -274 -117q-206 0 -324 158q-36 48 -69 133t-45 204h-217l100 100h112q1 47 6 100h-218l100 100h134q20 87 51 153.5t62 103.5q117 141 297 141z" /> +<glyph unicode="₽" d="M428 1200h350q67 0 120 -13t86 -31t57 -49.5t35 -56.5t17 -64.5t6.5 -60.5t0.5 -57v-16.5v-16.5q0 -36 -0.5 -57t-6.5 -61t-17 -65t-35 -57t-57 -50.5t-86 -31.5t-120 -13h-178l-2 -100h288q10 0 13 -6t-3 -14l-120 -160q-6 -8 -18 -14t-22 -6h-138v-175q0 -11 -5.5 -18 t-15.5 -7h-149q-10 0 -17.5 7.5t-7.5 17.5v175h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v100h-267q-10 0 -13 6t3 14l120 160q6 8 18 14t22 6h117v475q0 10 7.5 17.5t17.5 7.5zM600 1000v-300h203q64 0 86.5 33t22.5 119q0 84 -22.5 116t-86.5 32h-203z" /> +<glyph unicode="−" d="M250 700h800q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="⌛" d="M1000 1200v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-50v-100q0 -91 -49.5 -165.5t-130.5 -109.5q81 -35 130.5 -109.5t49.5 -165.5v-150h50q21 0 35.5 -14.5t14.5 -35.5v-150h-800v150q0 21 14.5 35.5t35.5 14.5h50v150q0 91 49.5 165.5t130.5 109.5q-81 35 -130.5 109.5 t-49.5 165.5v100h-50q-21 0 -35.5 14.5t-14.5 35.5v150h800zM400 1000v-100q0 -60 32.5 -109.5t87.5 -73.5q28 -12 44 -37t16 -55t-16 -55t-44 -37q-55 -24 -87.5 -73.5t-32.5 -109.5v-150h400v150q0 60 -32.5 109.5t-87.5 73.5q-28 12 -44 37t-16 55t16 55t44 37 q55 24 87.5 73.5t32.5 109.5v100h-400z" /> <glyph unicode="◼" horiz-adv-x="500" d="M0 0z" /> -<glyph unicode="☁" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" /> -<glyph unicode="✉" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" /> -<glyph unicode="✏" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" /> -<glyph unicode="" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" /> -<glyph unicode="" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q18 -55 86 -75.5t147 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" /> -<glyph unicode="" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" /> -<glyph unicode="" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" /> -<glyph unicode="" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" /> -<glyph unicode="" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" /> -<glyph unicode="" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" /> -<glyph unicode="" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" /> -<glyph unicode="" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" /> -<glyph unicode="" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" /> -<glyph unicode="" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" /> -<glyph unicode="" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" /> -<glyph unicode="" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" /> -<glyph unicode="" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" /> -<glyph unicode="" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" /> -<glyph unicode="" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" /> -<glyph unicode="" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" /> -<glyph unicode="" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" /> -<glyph unicode="" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" /> -<glyph unicode="" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" /> -<glyph unicode="" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" /> -<glyph unicode="" d="M0 25v475l200 700h800l199 -700l1 -475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" /> -<glyph unicode="" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" /> -<glyph unicode="" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" /> -<glyph unicode="" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" /> -<glyph unicode="" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" /> -<glyph unicode="" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" /> -<glyph unicode="" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" /> -<glyph unicode="" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" /> -<glyph unicode="" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" /> -<glyph unicode="" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" /> -<glyph unicode="" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" /> -<glyph unicode="" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" /> -<glyph unicode="" d="M0 700l1 475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" /> -<glyph unicode="" d="M1 700l1 475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" /> -<glyph unicode="" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" /> -<glyph unicode="" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" /> -<glyph unicode="" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" /> -<glyph unicode="" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" /> -<glyph unicode="" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" /> -<glyph unicode="" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v71l471 -1q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" /> -<glyph unicode="" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" /> -<glyph unicode="" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " /> -<glyph unicode="" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" /> -<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" /> -<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" /> -<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" /> -<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" /> -<glyph unicode="" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" /> -<glyph unicode="" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" /> -<glyph unicode="" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" /> -<glyph unicode="" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" /> -<glyph unicode="" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " /> -<glyph unicode="" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" /> -<glyph unicode="" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" /> -<glyph unicode="" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 139t-64 210zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q61 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l567 567l-137 137l-430 -431l-146 147z" /> -<glyph unicode="" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" /> -<glyph unicode="" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" /> -<glyph unicode="" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" /> -<glyph unicode="" d="M200 0l900 550l-900 550v-1100z" /> -<glyph unicode="" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" /> -<glyph unicode="" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" /> -<glyph unicode="" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" /> -<glyph unicode="" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" /> -<glyph unicode="" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" /> -<glyph unicode="" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" /> -<glyph unicode="" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" /> -<glyph unicode="" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h600v200h-600v-200z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141 z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM364 700h143q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5 q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-50 0 -90.5 -12t-75 -38.5t-53.5 -74.5t-19 -114zM500 300h200v100h-200 v-100z" /> -<glyph unicode="" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" /> -<glyph unicode="" d="M0 500v200h195q31 125 98.5 199.5t206.5 100.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200v-206 q149 48 201 206h-201v200h200q-25 74 -75.5 127t-124.5 77v-204h-200v203q-75 -23 -130 -77t-79 -126h209v-200h-210z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" /> -<glyph unicode="" d="M0 547l600 453v-300h600v-300h-600v-301z" /> -<glyph unicode="" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" /> -<glyph unicode="" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" /> -<glyph unicode="" d="M104 600h296v600h300v-600h298l-449 -600z" /> -<glyph unicode="" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" /> -<glyph unicode="" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" /> -<glyph unicode="" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" /> -<glyph unicode="" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5h-207q-21 0 -33 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" /> -<glyph unicode="" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111q1 1 1 6.5t-1.5 15t-3.5 17.5l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6 h-111v-100zM100 0h400v400h-400v-400zM200 900q-3 0 14 48t36 96l18 47l213 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" /> -<glyph unicode="" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" /> -<glyph unicode="" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" /> -<glyph unicode="" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" /> -<glyph unicode="" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" /> -<glyph unicode="" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 34 -48 36.5t-48 -29.5l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" /> -<glyph unicode="" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -20 -13 -28.5t-32 0.5l-94 78h-222l-94 -78q-19 -9 -32 -0.5t-13 28.5 v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" /> -<glyph unicode="" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" /> -<glyph unicode="" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" /> -<glyph unicode="" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" /> -<glyph unicode="" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" /> -<glyph unicode="" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" /> -<glyph unicode="" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" /> -<glyph unicode="" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" /> -<glyph unicode="" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" /> -<glyph unicode="" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" /> -<glyph unicode="" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" /> -<glyph unicode="" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" /> -<glyph unicode="" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" /> -<glyph unicode="" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" /> -<glyph unicode="" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM100 500v250v8v8v7t0.5 7t1.5 5.5t2 5t3 4t4.5 3.5t6 1.5t7.5 0.5h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35 q-55 337 -55 351zM1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" /> -<glyph unicode="" d="M74 350q0 21 13.5 35.5t33.5 14.5h18l117 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5q-18 -36 -18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-8 -3 -23 -8.5 t-65 -20t-103 -25t-132.5 -19.5t-158.5 -9q-125 0 -245.5 20.5t-178.5 40.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" /> -<glyph unicode="" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" /> -<glyph unicode="" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q124 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 213l100 212h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" /> -<glyph unicode="" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q124 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" /> -<glyph unicode="" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" /> -<glyph unicode="" d="M-101 651q0 72 54 110t139 38l302 -1l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 17 -10.5t26.5 -26t16.5 -36.5v-526q0 -13 -86 -93.5t-94 -80.5h-341q-16 0 -29.5 20t-19.5 41l-130 339h-107q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l107 89v502l-343 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM1000 201v600h200v-600h-200z" /> -<glyph unicode="" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6.5v7.5v6.5v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" /> -<glyph unicode="" d="M2 585q-16 -31 6 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85q0 -51 -0.5 -153.5t-0.5 -148.5q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM77 565l236 339h503 l89 -100v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" /> -<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM298 701l2 -201h300l-2 -194l402 294l-402 298v-197h-300z" /> -<glyph unicode="" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l402 -294l-2 194h300l2 201h-300v197z" /> -<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" /> -<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" /> -<glyph unicode="" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60 q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55t-20 -57q42 -71 87 -80q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q104 -3 221 112q30 29 47 47t34.5 49t20.5 62q-14 9 -37 9.5t-36 7.5q-14 7 -49 15t-52 19q-9 0 -39.5 -0.5 t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5t5.5 57.5 q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 39 2 44q31 -13 58 -14.5t39 3.5l11 4q7 36 -16.5 53.5t-64.5 28.5t-56 23q-19 -3 -37 0 q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5zM518 916q3 12 16 30t16 25q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -24 17 -66.5t17 -43.5 q-9 2 -31 5t-36 5t-32 8t-30 14zM692 1003h1h-1z" /> -<glyph unicode="" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" /> -<glyph unicode="" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" /> -<glyph unicode="" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" /> -<glyph unicode="" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" /> -<glyph unicode="" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" /> -<glyph unicode="" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM514 609q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" /> -<glyph unicode="" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -78.5 -16.5t-67.5 -51.5l-389 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23 q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60 l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" /> -<glyph unicode="" d="M80 784q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100q-71 70 -104.5 105.5t-77 89.5t-61 99 t-17.5 91zM250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-105 48.5q-74 0 -132 -83l-118 -171l-114 174q-51 80 -123 80q-60 0 -109.5 -49.5t-49.5 -118.5z" /> -<glyph unicode="" d="M57 353q0 -95 66 -159l141 -142q68 -66 159 -66q93 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-8 9 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141q7 -7 19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -17q47 -49 77 -100l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" /> -<glyph unicode="" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" /> -<glyph unicode="" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" /> -<glyph unicode="" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335q-6 1 -15.5 4t-11.5 3q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5 v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5 zM700 237q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" /> -<glyph unicode="" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -28 16.5 -69.5t28 -62.5t41.5 -72h241v-100h-197q8 -50 -2.5 -115 t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q33 1 103 -16t103 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" /> -<glyph unicode="" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" /> -<glyph unicode="" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" /> -<glyph unicode="" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" /> -<glyph unicode="" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" /> -<glyph unicode="" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" /> -<glyph unicode="" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" /> -<glyph unicode="" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" /> -<glyph unicode="" d="M217 519q8 -19 31 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8h9q14 0 26 15q11 13 274.5 321.5t264.5 308.5q14 19 5 36q-8 17 -31 17l-301 -1q1 4 78 219.5t79 227.5q2 15 -5 27l-9 9h-9q-15 0 -25 -16q-4 -6 -98 -111.5t-228.5 -257t-209.5 -237.5q-16 -19 -6 -41 z" /> -<glyph unicode="" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " /> -<glyph unicode="" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 400l697 1l3 699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l249 -237l-1 697zM900 150h100v50h-100v-50z" /> -<glyph unicode="" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" /> -<glyph unicode="" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" /> -<glyph unicode="" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" /> -<glyph unicode="" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" /> -<glyph unicode="" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -116q-25 -17 -43.5 -51.5t-18.5 -65.5v-359z" /> -<glyph unicode="" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" /> -<glyph unicode="" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" /> -<glyph unicode="" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q17 18 13.5 41t-22.5 37l-192 136q-19 14 -45 12t-42 -19l-118 -118q-142 101 -268 227t-227 268l118 118q17 17 20 41.5t-11 44.5 l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" /> -<glyph unicode="" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-20 0 -35 14.5t-15 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" /> -<glyph unicode="" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" /> -<glyph unicode="" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" /> -<glyph unicode="" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" /> -<glyph unicode="" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" /> -<glyph unicode="" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" /> -<glyph unicode="" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300h200 l-300 -300z" /> -<glyph unicode="" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104.5t60.5 178.5q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" /> -<glyph unicode="" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" /> -<glyph unicode="" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -11.5t1 -11.5q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" /> +<glyph unicode="☁" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -206.5q0 -121 -85 -207.5t-205 -86.5h-750q-79 0 -135.5 57t-56.5 137q0 69 42.5 122.5t108.5 67.5q-2 12 -2 37q0 153 108 260.5t260 107.5z" /> +<glyph unicode="⛺" d="M774 1193.5q16 -9.5 20.5 -27t-5.5 -33.5l-136 -187l467 -746h30q20 0 35 -18.5t15 -39.5v-42h-1200v42q0 21 15 39.5t35 18.5h30l468 746l-135 183q-10 16 -5.5 34t20.5 28t34 5.5t28 -20.5l111 -148l112 150q9 16 27 20.5t34 -5zM600 200h377l-182 112l-195 534v-646z " /> +<glyph unicode="✉" d="M25 1100h1150q10 0 12.5 -5t-5.5 -13l-564 -567q-8 -8 -18 -8t-18 8l-564 567q-8 8 -5.5 13t12.5 5zM18 882l264 -264q8 -8 8 -18t-8 -18l-264 -264q-8 -8 -13 -5.5t-5 12.5v550q0 10 5 12.5t13 -5.5zM918 618l264 264q8 8 13 5.5t5 -12.5v-550q0 -10 -5 -12.5t-13 5.5 l-264 264q-8 8 -8 18t8 18zM818 482l364 -364q8 -8 5.5 -13t-12.5 -5h-1150q-10 0 -12.5 5t5.5 13l364 364q8 8 18 8t18 -8l164 -164q8 -8 18 -8t18 8l164 164q8 8 18 8t18 -8z" /> +<glyph unicode="✏" d="M1011 1210q19 0 33 -13l153 -153q13 -14 13 -33t-13 -33l-99 -92l-214 214l95 96q13 14 32 14zM1013 800l-615 -614l-214 214l614 614zM317 96l-333 -112l110 335z" /> +<glyph unicode="" d="M700 650v-550h250q21 0 35.5 -14.5t14.5 -35.5v-50h-800v50q0 21 14.5 35.5t35.5 14.5h250v550l-500 550h1200z" /> +<glyph unicode="" d="M368 1017l645 163q39 15 63 0t24 -49v-831q0 -55 -41.5 -95.5t-111.5 -63.5q-79 -25 -147 -4.5t-86 75t25.5 111.5t122.5 82q72 24 138 8v521l-600 -155v-606q0 -42 -44 -90t-109 -69q-79 -26 -147 -5.5t-86 75.5t25.5 111.5t122.5 82.5q72 24 138 7v639q0 38 14.5 59 t53.5 34z" /> +<glyph unicode="" d="M500 1191q100 0 191 -39t156.5 -104.5t104.5 -156.5t39 -191l-1 -2l1 -5q0 -141 -78 -262l275 -274q23 -26 22.5 -44.5t-22.5 -42.5l-59 -58q-26 -20 -46.5 -20t-39.5 20l-275 274q-119 -77 -261 -77l-5 1l-2 -1q-100 0 -191 39t-156.5 104.5t-104.5 156.5t-39 191 t39 191t104.5 156.5t156.5 104.5t191 39zM500 1022q-88 0 -162 -43t-117 -117t-43 -162t43 -162t117 -117t162 -43t162 43t117 117t43 162t-43 162t-117 117t-162 43z" /> +<glyph unicode="" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104z" /> +<glyph unicode="" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429z" /> +<glyph unicode="" d="M407 800l131 353q7 19 17.5 19t17.5 -19l129 -353h421q21 0 24 -8.5t-14 -20.5l-342 -249l130 -401q7 -20 -0.5 -25.5t-24.5 6.5l-343 246l-342 -247q-17 -12 -24.5 -6.5t-0.5 25.5l130 400l-347 251q-17 12 -14 20.5t23 8.5h429zM477 700h-240l197 -142l-74 -226 l193 139l195 -140l-74 229l192 140h-234l-78 211z" /> +<glyph unicode="" d="M600 1200q124 0 212 -88t88 -212v-250q0 -46 -31 -98t-69 -52v-75q0 -10 6 -21.5t15 -17.5l358 -230q9 -5 15 -16.5t6 -21.5v-93q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v93q0 10 6 21.5t15 16.5l358 230q9 6 15 17.5t6 21.5v75q-38 0 -69 52 t-31 98v250q0 124 88 212t212 88z" /> +<glyph unicode="" d="M25 1100h1150q10 0 17.5 -7.5t7.5 -17.5v-1050q0 -10 -7.5 -17.5t-17.5 -7.5h-1150q-10 0 -17.5 7.5t-7.5 17.5v1050q0 10 7.5 17.5t17.5 7.5zM100 1000v-100h100v100h-100zM875 1000h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5t17.5 -7.5h550 q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM1000 1000v-100h100v100h-100zM100 800v-100h100v100h-100zM1000 800v-100h100v100h-100zM100 600v-100h100v100h-100zM1000 600v-100h100v100h-100zM875 500h-550q-10 0 -17.5 -7.5t-7.5 -17.5v-350q0 -10 7.5 -17.5 t17.5 -7.5h550q10 0 17.5 7.5t7.5 17.5v350q0 10 -7.5 17.5t-17.5 7.5zM100 400v-100h100v100h-100zM1000 400v-100h100v100h-100zM100 200v-100h100v100h-100zM1000 200v-100h100v100h-100z" /> +<glyph unicode="" d="M50 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM50 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM650 500h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM850 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 700h200q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM850 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5 t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 1100h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200 q0 21 14.5 35.5t35.5 14.5zM50 700h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 700h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700 q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM50 300h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5zM450 300h700q21 0 35.5 -14.5t14.5 -35.5v-200 q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M465 477l571 571q8 8 18 8t17 -8l177 -177q8 -7 8 -17t-8 -18l-783 -784q-7 -8 -17.5 -8t-17.5 8l-384 384q-8 8 -8 18t8 17l177 177q7 8 17 8t18 -8l171 -171q7 -7 18 -7t18 7z" /> +<glyph unicode="" d="M904 1083l178 -179q8 -8 8 -18.5t-8 -17.5l-267 -268l267 -268q8 -7 8 -17.5t-8 -18.5l-178 -178q-8 -8 -18.5 -8t-17.5 8l-268 267l-268 -267q-7 -8 -17.5 -8t-18.5 8l-178 178q-8 8 -8 18.5t8 17.5l267 268l-267 268q-8 7 -8 17.5t8 18.5l178 178q8 8 18.5 8t17.5 -8 l268 -267l268 268q7 7 17.5 7t18.5 -7z" /> +<glyph unicode="" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM425 900h150q10 0 17.5 -7.5t7.5 -17.5v-75h75q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5 t-17.5 -7.5h-75v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-75q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v75q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M507 1177q98 0 187.5 -38.5t154.5 -103.5t103.5 -154.5t38.5 -187.5q0 -141 -78 -262l300 -299q8 -8 8 -18.5t-8 -18.5l-109 -108q-7 -8 -17.5 -8t-18.5 8l-300 299q-119 -77 -261 -77q-98 0 -188 38.5t-154.5 103t-103 154.5t-38.5 188t38.5 187.5t103 154.5 t154.5 103.5t188 38.5zM506.5 1023q-89.5 0 -165.5 -44t-120 -120.5t-44 -166t44 -165.5t120 -120t165.5 -44t166 44t120.5 120t44 165.5t-44 166t-120.5 120.5t-166 44zM325 800h350q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-350q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M550 1200h100q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM800 975v166q167 -62 272 -209.5t105 -331.5q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5 t-184.5 123t-123 184.5t-45.5 224q0 184 105 331.5t272 209.5v-166q-103 -55 -165 -155t-62 -220q0 -116 57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5q0 120 -62 220t-165 155z" /> +<glyph unicode="" d="M1025 1200h150q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM725 800h150q10 0 17.5 -7.5t7.5 -17.5v-750q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v750 q0 10 7.5 17.5t17.5 7.5zM425 500h150q10 0 17.5 -7.5t7.5 -17.5v-450q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v450q0 10 7.5 17.5t17.5 7.5zM125 300h150q10 0 17.5 -7.5t7.5 -17.5v-250q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5 v250q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M600 1174q33 0 74 -5l38 -152l5 -1q49 -14 94 -39l5 -2l134 80q61 -48 104 -105l-80 -134l3 -5q25 -44 39 -93l1 -6l152 -38q5 -43 5 -73q0 -34 -5 -74l-152 -38l-1 -6q-15 -49 -39 -93l-3 -5l80 -134q-48 -61 -104 -105l-134 81l-5 -3q-44 -25 -94 -39l-5 -2l-38 -151 q-43 -5 -74 -5q-33 0 -74 5l-38 151l-5 2q-49 14 -94 39l-5 3l-134 -81q-60 48 -104 105l80 134l-3 5q-25 45 -38 93l-2 6l-151 38q-6 42 -6 74q0 33 6 73l151 38l2 6q13 48 38 93l3 5l-80 134q47 61 105 105l133 -80l5 2q45 25 94 39l5 1l38 152q43 5 74 5zM600 815 q-89 0 -152 -63t-63 -151.5t63 -151.5t152 -63t152 63t63 151.5t-63 151.5t-152 63z" /> +<glyph unicode="" d="M500 1300h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-75h-1100v75q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5zM500 1200v-100h300v100h-300zM1100 900v-800q0 -41 -29.5 -70.5t-70.5 -29.5h-700q-41 0 -70.5 29.5t-29.5 70.5 v800h900zM300 800v-700h100v700h-100zM500 800v-700h100v700h-100zM700 800v-700h100v700h-100zM900 800v-700h100v700h-100z" /> +<glyph unicode="" d="M18 618l620 608q8 7 18.5 7t17.5 -7l608 -608q8 -8 5.5 -13t-12.5 -5h-175v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v375h-300v-375q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v575h-175q-10 0 -12.5 5t5.5 13z" /> +<glyph unicode="" d="M600 1200v-400q0 -41 29.5 -70.5t70.5 -29.5h300v-650q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5h450zM1000 800h-250q-21 0 -35.5 14.5t-14.5 35.5v250z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h50q10 0 17.5 -7.5t7.5 -17.5v-275h175q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M1300 0h-538l-41 400h-242l-41 -400h-538l431 1200h209l-21 -300h162l-20 300h208zM515 800l-27 -300h224l-27 300h-170z" /> +<glyph unicode="" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-450h191q20 0 25.5 -11.5t-7.5 -27.5l-327 -400q-13 -16 -32 -16t-32 16l-327 400q-13 16 -7.5 27.5t25.5 11.5h191v450q0 21 14.5 35.5t35.5 14.5zM1125 400h50q10 0 17.5 -7.5t7.5 -17.5v-350q0 -10 -7.5 -17.5t-17.5 -7.5 h-1050q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h50q10 0 17.5 -7.5t7.5 -17.5v-175h900v175q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM525 900h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -275q-13 -16 -32 -16t-32 16l-223 275q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z " /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM632 914l223 -275q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5l223 275q13 16 32 16 t32 -16z" /> +<glyph unicode="" d="M225 1200h750q10 0 19.5 -7t12.5 -17l186 -652q7 -24 7 -49v-425q0 -12 -4 -27t-9 -17q-12 -6 -37 -6h-1100q-12 0 -27 4t-17 8q-6 13 -6 38l1 425q0 25 7 49l185 652q3 10 12.5 17t19.5 7zM878 1000h-556q-10 0 -19 -7t-11 -18l-87 -450q-2 -11 4 -18t16 -7h150 q10 0 19.5 -7t11.5 -17l38 -152q2 -10 11.5 -17t19.5 -7h250q10 0 19.5 7t11.5 17l38 152q2 10 11.5 17t19.5 7h150q10 0 16 7t4 18l-87 450q-2 11 -11 18t-19 7z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM540 820l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" /> +<glyph unicode="" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-362q0 -10 -7.5 -17.5t-17.5 -7.5h-362q-11 0 -13 5.5t5 12.5l133 133q-109 76 -238 76q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5h150q0 -117 -45.5 -224 t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117z" /> +<glyph unicode="" d="M947 1060l135 135q7 7 12.5 5t5.5 -13v-361q0 -11 -7.5 -18.5t-18.5 -7.5h-361q-11 0 -13 5.5t5 12.5l134 134q-110 75 -239 75q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5h-150q0 117 45.5 224t123 184.5t184.5 123t224 45.5q192 0 347 -117zM1027 600h150 q0 -117 -45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5q-192 0 -348 118l-134 -134q-7 -8 -12.5 -5.5t-5.5 12.5v360q0 11 7.5 18.5t18.5 7.5h360q10 0 12.5 -5.5t-5.5 -12.5l-133 -133q110 -76 240 -76q116 0 214.5 57t155.5 155.5t57 214.5z" /> +<glyph unicode="" d="M125 1200h1050q10 0 17.5 -7.5t7.5 -17.5v-1150q0 -10 -7.5 -17.5t-17.5 -7.5h-1050q-10 0 -17.5 7.5t-7.5 17.5v1150q0 10 7.5 17.5t17.5 7.5zM1075 1000h-850q-10 0 -17.5 -7.5t-7.5 -17.5v-850q0 -10 7.5 -17.5t17.5 -7.5h850q10 0 17.5 7.5t7.5 17.5v850 q0 10 -7.5 17.5t-17.5 7.5zM325 900h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 900h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 700h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 700h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 500h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 500h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5zM325 300h50q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM525 300h450q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-450q-10 0 -17.5 7.5t-7.5 17.5v50 q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M900 800v200q0 83 -58.5 141.5t-141.5 58.5h-300q-82 0 -141 -59t-59 -141v-200h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h900q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-100zM400 800v150q0 21 15 35.5t35 14.5h200 q20 0 35 -14.5t15 -35.5v-150h-300z" /> +<glyph unicode="" d="M125 1100h50q10 0 17.5 -7.5t7.5 -17.5v-1075h-100v1075q0 10 7.5 17.5t17.5 7.5zM1075 1052q4 0 9 -2q16 -6 16 -23v-421q0 -6 -3 -12q-33 -59 -66.5 -99t-65.5 -58t-56.5 -24.5t-52.5 -6.5q-26 0 -57.5 6.5t-52.5 13.5t-60 21q-41 15 -63 22.5t-57.5 15t-65.5 7.5 q-85 0 -160 -57q-7 -5 -15 -5q-6 0 -11 3q-14 7 -14 22v438q22 55 82 98.5t119 46.5q23 2 43 0.5t43 -7t32.5 -8.5t38 -13t32.5 -11q41 -14 63.5 -21t57 -14t63.5 -7q103 0 183 87q7 8 18 8z" /> +<glyph unicode="" d="M600 1175q116 0 227 -49.5t192.5 -131t131 -192.5t49.5 -227v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v300q0 127 -70.5 231.5t-184.5 161.5t-245 57t-245 -57t-184.5 -161.5t-70.5 -231.5v-300q0 -10 -7.5 -17.5t-17.5 -7.5h-50 q-10 0 -17.5 7.5t-7.5 17.5v300q0 116 49.5 227t131 192.5t192.5 131t227 49.5zM220 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460q0 8 6 14t14 6zM820 500h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14v460 q0 8 6 14t14 6z" /> +<glyph unicode="" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM900 668l120 120q7 7 17 7t17 -7l34 -34q7 -7 7 -17t-7 -17l-120 -120l120 -120q7 -7 7 -17 t-7 -17l-34 -34q-7 -7 -17 -7t-17 7l-120 119l-120 -119q-7 -7 -17 -7t-17 7l-34 34q-7 7 -7 17t7 17l119 120l-119 120q-7 7 -7 17t7 17l34 34q7 8 17 8t17 -8z" /> +<glyph unicode="" d="M321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6 l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238q-6 8 -4.5 18t9.5 17l29 22q7 5 15 5z" /> +<glyph unicode="" d="M967 1004h3q11 -1 17 -10q135 -179 135 -396q0 -105 -34 -206.5t-98 -185.5q-7 -9 -17 -10h-3q-9 0 -16 6l-42 34q-8 6 -9 16t5 18q111 150 111 328q0 90 -29.5 176t-84.5 157q-6 9 -5 19t10 16l42 33q7 5 15 5zM321 814l258 172q9 6 15 2.5t6 -13.5v-750q0 -10 -6 -13.5 t-15 2.5l-258 172q-21 14 -46 14h-250q-10 0 -17.5 7.5t-7.5 17.5v350q0 10 7.5 17.5t17.5 7.5h250q25 0 46 14zM766 900h4q10 -1 16 -10q96 -129 96 -290q0 -154 -90 -281q-6 -9 -17 -10l-3 -1q-9 0 -16 6l-29 23q-7 7 -8.5 16.5t4.5 17.5q72 103 72 229q0 132 -78 238 q-6 8 -4.5 18.5t9.5 16.5l29 22q7 5 15 5z" /> +<glyph unicode="" d="M500 900h100v-100h-100v-100h-400v-100h-100v600h500v-300zM1200 700h-200v-100h200v-200h-300v300h-200v300h-100v200h600v-500zM100 1100v-300h300v300h-300zM800 1100v-300h300v300h-300zM300 900h-100v100h100v-100zM1000 900h-100v100h100v-100zM300 500h200v-500 h-500v500h200v100h100v-100zM800 300h200v-100h-100v-100h-200v100h-100v100h100v200h-200v100h300v-300zM100 400v-300h300v300h-300zM300 200h-100v100h100v-100zM1200 200h-100v100h100v-100zM700 0h-100v100h100v-100zM1200 0h-300v100h300v-100z" /> +<glyph unicode="" d="M100 200h-100v1000h100v-1000zM300 200h-100v1000h100v-1000zM700 200h-200v1000h200v-1000zM900 200h-100v1000h100v-1000zM1200 200h-200v1000h200v-1000zM400 0h-300v100h300v-100zM600 0h-100v91h100v-91zM800 0h-100v91h100v-91zM1100 0h-200v91h200v-91z" /> +<glyph unicode="" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" /> +<glyph unicode="" d="M500 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-682 682l1 475q0 10 7.5 17.5t17.5 7.5h474zM800 1200l682 -682q8 -8 8 -18t-8 -18l-464 -464q-8 -8 -18 -8t-18 8l-56 56l424 426l-700 700h150zM319.5 1024.5q-29.5 29.5 -71 29.5t-71 -29.5 t-29.5 -71.5t29.5 -71.5t71 -29.5t71 29.5t29.5 71.5t-29.5 71.5z" /> +<glyph unicode="" d="M300 1200h825q75 0 75 -75v-900q0 -25 -18 -43l-64 -64q-8 -8 -13 -5.5t-5 12.5v950q0 10 -7.5 17.5t-17.5 7.5h-700q-25 0 -43 -18l-64 -64q-8 -8 -5.5 -13t12.5 -5h700q10 0 17.5 -7.5t7.5 -17.5v-950q0 -10 -7.5 -17.5t-17.5 -7.5h-850q-10 0 -17.5 7.5t-7.5 17.5v975 q0 25 18 43l139 139q18 18 43 18z" /> +<glyph unicode="" d="M250 1200h800q21 0 35.5 -14.5t14.5 -35.5v-1150l-450 444l-450 -445v1151q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M822 1200h-444q-11 0 -19 -7.5t-9 -17.5l-78 -301q-7 -24 7 -45l57 -108q6 -9 17.5 -15t21.5 -6h450q10 0 21.5 6t17.5 15l62 108q14 21 7 45l-83 301q-1 10 -9 17.5t-19 7.5zM1175 800h-150q-10 0 -21 -6.5t-15 -15.5l-78 -156q-4 -9 -15 -15.5t-21 -6.5h-550 q-10 0 -21 6.5t-15 15.5l-78 156q-4 9 -15 15.5t-21 6.5h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-650q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h750q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5 t7.5 17.5v650q0 10 -7.5 17.5t-17.5 7.5zM850 200h-500q-10 0 -19.5 -7t-11.5 -17l-38 -152q-2 -10 3.5 -17t15.5 -7h600q10 0 15.5 7t3.5 17l-38 152q-2 10 -11.5 17t-19.5 7z" /> +<glyph unicode="" d="M500 1100h200q56 0 102.5 -20.5t72.5 -50t44 -59t25 -50.5l6 -20h150q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5h150q2 8 6.5 21.5t24 48t45 61t72 48t102.5 21.5zM900 800v-100 h100v100h-100zM600 730q-95 0 -162.5 -67.5t-67.5 -162.5t67.5 -162.5t162.5 -67.5t162.5 67.5t67.5 162.5t-67.5 162.5t-162.5 67.5zM600 603q43 0 73 -30t30 -73t-30 -73t-73 -30t-73 30t-30 73t30 73t73 30z" /> +<glyph unicode="" d="M681 1199l385 -998q20 -50 60 -92q18 -19 36.5 -29.5t27.5 -11.5l10 -2v-66h-417v66q53 0 75 43.5t5 88.5l-82 222h-391q-58 -145 -92 -234q-11 -34 -6.5 -57t25.5 -37t46 -20t55 -6v-66h-365v66q56 24 84 52q12 12 25 30.5t20 31.5l7 13l399 1006h93zM416 521h340 l-162 457z" /> +<glyph unicode="" d="M753 641q5 -1 14.5 -4.5t36 -15.5t50.5 -26.5t53.5 -40t50.5 -54.5t35.5 -70t14.5 -87q0 -67 -27.5 -125.5t-71.5 -97.5t-98.5 -66.5t-108.5 -40.5t-102 -13h-500v89q41 7 70.5 32.5t29.5 65.5v827q0 24 -0.5 34t-3.5 24t-8.5 19.5t-17 13.5t-28 12.5t-42.5 11.5v71 l471 -1q57 0 115.5 -20.5t108 -57t80.5 -94t31 -124.5q0 -51 -15.5 -96.5t-38 -74.5t-45 -50.5t-38.5 -30.5zM400 700h139q78 0 130.5 48.5t52.5 122.5q0 41 -8.5 70.5t-29.5 55.5t-62.5 39.5t-103.5 13.5h-118v-350zM400 200h216q80 0 121 50.5t41 130.5q0 90 -62.5 154.5 t-156.5 64.5h-159v-400z" /> +<glyph unicode="" d="M877 1200l2 -57q-83 -19 -116 -45.5t-40 -66.5l-132 -839q-9 -49 13 -69t96 -26v-97h-500v97q186 16 200 98l173 832q3 17 3 30t-1.5 22.5t-9 17.5t-13.5 12.5t-21.5 10t-26 8.5t-33.5 10q-13 3 -19 5v57h425z" /> +<glyph unicode="" d="M1300 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM175 1000h-75v-800h75l-125 -167l-125 167h75v800h-75l125 167z" /> +<glyph unicode="" d="M1100 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-650q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v650h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM1167 50l-167 -125v75h-800v-75l-167 125l167 125v-75h800v75z" /> +<glyph unicode="" d="M50 1100h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M250 1100h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM250 500h700q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000 q-21 0 -35.5 14.5t-14.5 35.5zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5zM0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5z" /> +<glyph unicode="" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 800h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 500h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 1100h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 800h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 500h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 500h800q21 0 35.5 -14.5t14.5 -35.5v-100 q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM350 200h800 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M400 0h-100v1100h100v-1100zM550 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM267 550l-167 -125v75h-200v100h200v75zM550 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM550 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM900 0h-100v1100h100v-1100zM50 800h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM1100 600h200v-100h-200v-75l-167 125l167 125v-75zM50 500h300q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5zM50 200h600 q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-600q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M75 1000h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53v650q0 31 22 53t53 22zM1200 300l-300 300l300 300v-600z" /> +<glyph unicode="" d="M44 1100h1112q18 0 31 -13t13 -31v-1012q0 -18 -13 -31t-31 -13h-1112q-18 0 -31 13t-13 31v1012q0 18 13 31t31 13zM100 1000v-737l247 182l298 -131l-74 156l293 318l236 -288v500h-1000zM342 884q56 0 95 -39t39 -94.5t-39 -95t-95 -39.5t-95 39.5t-39 95t39 94.5 t95 39z" /> +<glyph unicode="" d="M648 1169q117 0 216 -60t156.5 -161t57.5 -218q0 -115 -70 -258q-69 -109 -158 -225.5t-143 -179.5l-54 -62q-9 8 -25.5 24.5t-63.5 67.5t-91 103t-98.5 128t-95.5 148q-60 132 -60 249q0 88 34 169.5t91.5 142t137 96.5t166.5 36zM652.5 974q-91.5 0 -156.5 -65 t-65 -157t65 -156.5t156.5 -64.5t156.5 64.5t65 156.5t-65 157t-156.5 65z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 173v854q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57z" /> +<glyph unicode="" d="M554 1295q21 -72 57.5 -143.5t76 -130t83 -118t82.5 -117t70 -116t49.5 -126t18.5 -136.5q0 -71 -25.5 -135t-68.5 -111t-99 -82t-118.5 -54t-125.5 -23q-84 5 -161.5 34t-139.5 78.5t-99 125t-37 164.5q0 69 18 136.5t49.5 126.5t69.5 116.5t81.5 117.5t83.5 119 t76.5 131t58.5 143zM344 710q-23 -33 -43.5 -70.5t-40.5 -102.5t-17 -123q1 -37 14.5 -69.5t30 -52t41 -37t38.5 -24.5t33 -15q21 -7 32 -1t13 22l6 34q2 10 -2.5 22t-13.5 19q-5 4 -14 12t-29.5 40.5t-32.5 73.5q-26 89 6 271q2 11 -6 11q-8 1 -15 -10z" /> +<glyph unicode="" d="M1000 1013l108 115q2 1 5 2t13 2t20.5 -1t25 -9.5t28.5 -21.5q22 -22 27 -43t0 -32l-6 -10l-108 -115zM350 1100h400q50 0 105 -13l-187 -187h-368q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v182l200 200v-332 q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM1009 803l-362 -362l-161 -50l55 170l355 355z" /> +<glyph unicode="" d="M350 1100h361q-164 -146 -216 -200h-195q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-103q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M824 1073l339 -301q8 -7 8 -17.5t-8 -17.5l-340 -306q-7 -6 -12.5 -4t-6.5 11v203q-26 1 -54.5 0t-78.5 -7.5t-92 -17.5t-86 -35t-70 -57q10 59 33 108t51.5 81.5t65 58.5t68.5 40.5t67 24.5t56 13.5t40 4.5v210q1 10 6.5 12.5t13.5 -4.5z" /> +<glyph unicode="" d="M350 1100h350q60 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-219q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5z M643 639l395 395q7 7 17.5 7t17.5 -7l101 -101q7 -7 7 -17.5t-7 -17.5l-531 -532q-7 -7 -17.5 -7t-17.5 7l-248 248q-7 7 -7 17.5t7 17.5l101 101q7 7 17.5 7t17.5 -7l111 -111q8 -7 18 -7t18 7z" /> +<glyph unicode="" d="M318 918l264 264q8 8 18 8t18 -8l260 -264q7 -8 4.5 -13t-12.5 -5h-170v-200h200v173q0 10 5 12t13 -5l264 -260q8 -7 8 -17.5t-8 -17.5l-264 -265q-8 -7 -13 -5t-5 12v173h-200v-200h170q10 0 12.5 -5t-4.5 -13l-260 -264q-8 -8 -18 -8t-18 8l-264 264q-8 8 -5.5 13 t12.5 5h175v200h-200v-173q0 -10 -5 -12t-13 5l-264 265q-8 7 -8 17.5t8 17.5l264 260q8 7 13 5t5 -12v-173h200v200h-175q-10 0 -12.5 5t5.5 13z" /> +<glyph unicode="" d="M250 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M50 1100h100q21 0 35.5 -14.5t14.5 -35.5v-438l464 453q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5 t-14.5 35.5v1000q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M1200 1050v-1000q0 -21 -10.5 -25t-25.5 10l-464 453v-438q0 -21 -10.5 -25t-25.5 10l-492 480q-15 14 -15 35t15 35l492 480q15 14 25.5 10t10.5 -25v-438l464 453q15 14 25.5 10t10.5 -25z" /> +<glyph unicode="" d="M243 1074l814 -498q18 -11 18 -26t-18 -26l-814 -498q-18 -11 -30.5 -4t-12.5 28v1000q0 21 12.5 28t30.5 -4z" /> +<glyph unicode="" d="M250 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM650 1000h200q21 0 35.5 -14.5t14.5 -35.5v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v800 q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M1100 950v-800q0 -21 -14.5 -35.5t-35.5 -14.5h-800q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5z" /> +<glyph unicode="" d="M500 612v438q0 21 10.5 25t25.5 -10l492 -480q15 -14 15 -35t-15 -35l-492 -480q-15 -14 -25.5 -10t-10.5 25v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10z" /> +<glyph unicode="" d="M1048 1102l100 1q20 0 35 -14.5t15 -35.5l5 -1000q0 -21 -14.5 -35.5t-35.5 -14.5l-100 -1q-21 0 -35.5 14.5t-14.5 35.5l-2 437l-463 -454q-14 -15 -24.5 -10.5t-10.5 25.5l-2 437l-462 -455q-15 -14 -25.5 -9.5t-10.5 24.5l-5 1000q0 21 10.5 25.5t25.5 -10.5l466 -450 l-2 438q0 20 10.5 24.5t25.5 -9.5l466 -451l-2 438q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M850 1100h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-464 -453q-15 -14 -25.5 -10t-10.5 25v1000q0 21 10.5 25t25.5 -10l464 -453v438q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M686 1081l501 -540q15 -15 10.5 -26t-26.5 -11h-1042q-22 0 -26.5 11t10.5 26l501 540q15 15 36 15t36 -15zM150 400h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M885 900l-352 -353l352 -353l-197 -198l-552 552l552 550z" /> +<glyph unicode="" d="M1064 547l-551 -551l-198 198l353 353l-353 353l198 198z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM650 900h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-150 q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5h150v-150q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v150h150q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-150v150q0 21 -14.5 35.5t-35.5 14.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM850 700h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5 t35.5 -14.5h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM741.5 913q-12.5 0 -21.5 -9l-120 -120l-120 120q-9 9 -21.5 9 t-21.5 -9l-141 -141q-9 -9 -9 -21.5t9 -21.5l120 -120l-120 -120q-9 -9 -9 -21.5t9 -21.5l141 -141q9 -9 21.5 -9t21.5 9l120 120l120 -120q9 -9 21.5 -9t21.5 9l141 141q9 9 9 21.5t-9 21.5l-120 120l120 120q9 9 9 21.5t-9 21.5l-141 141q-9 9 -21.5 9z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM546 623l-84 85q-7 7 -17.5 7t-18.5 -7l-139 -139q-7 -8 -7 -18t7 -18 l242 -241q7 -8 17.5 -8t17.5 8l375 375q7 7 7 17.5t-7 18.5l-139 139q-7 7 -17.5 7t-17.5 -7z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM588 941q-29 0 -59 -5.5t-63 -20.5t-58 -38.5t-41.5 -63t-16.5 -89.5 q0 -25 20 -25h131q30 -5 35 11q6 20 20.5 28t45.5 8q20 0 31.5 -10.5t11.5 -28.5q0 -23 -7 -34t-26 -18q-1 0 -13.5 -4t-19.5 -7.5t-20 -10.5t-22 -17t-18.5 -24t-15.5 -35t-8 -46q-1 -8 5.5 -16.5t20.5 -8.5h173q7 0 22 8t35 28t37.5 48t29.5 74t12 100q0 47 -17 83 t-42.5 57t-59.5 34.5t-64 18t-59 4.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM675 1000h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5 t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5zM675 700h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h75v-200h-75q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h350q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5 t-17.5 7.5h-75v275q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M525 1200h150q10 0 17.5 -7.5t7.5 -17.5v-194q103 -27 178.5 -102.5t102.5 -178.5h194q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-194q-27 -103 -102.5 -178.5t-178.5 -102.5v-194q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v194 q-103 27 -178.5 102.5t-102.5 178.5h-194q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h194q27 103 102.5 178.5t178.5 102.5v194q0 10 7.5 17.5t17.5 7.5zM700 893v-168q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v168q-68 -23 -119 -74 t-74 -119h168q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-168q23 -68 74 -119t119 -74v168q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-168q68 23 119 74t74 119h-168q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h168 q-23 68 -74 119t-119 74z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM759 823l64 -64q7 -7 7 -17.5t-7 -17.5l-124 -124l124 -124q7 -7 7 -17.5t-7 -17.5l-64 -64q-7 -7 -17.5 -7t-17.5 7l-124 124l-124 -124q-7 -7 -17.5 -7t-17.5 7l-64 64 q-7 7 -7 17.5t7 17.5l124 124l-124 124q-7 7 -7 17.5t7 17.5l64 64q7 7 17.5 7t17.5 -7l124 -124l124 124q7 7 17.5 7t17.5 -7z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5t57 -214.5 t155.5 -155.5t214.5 -57t214.5 57t155.5 155.5t57 214.5t-57 214.5t-155.5 155.5t-214.5 57zM782 788l106 -106q7 -7 7 -17.5t-7 -17.5l-320 -321q-8 -7 -18 -7t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l197 197q7 7 17.5 7t17.5 -7z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM600 1027q-116 0 -214.5 -57t-155.5 -155.5t-57 -214.5q0 -120 65 -225 l587 587q-105 65 -225 65zM965 819l-584 -584q104 -62 219 -62q116 0 214.5 57t155.5 155.5t57 214.5q0 115 -62 219z" /> +<glyph unicode="" d="M39 582l522 427q16 13 27.5 8t11.5 -26v-291h550q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-550v-291q0 -21 -11.5 -26t-27.5 8l-522 427q-16 13 -16 32t16 32z" /> +<glyph unicode="" d="M639 1009l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291h-550q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h550v291q0 21 11.5 26t27.5 -8z" /> +<glyph unicode="" d="M682 1161l427 -522q13 -16 8 -27.5t-26 -11.5h-291v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v550h-291q-21 0 -26 11.5t8 27.5l427 522q13 16 32 16t32 -16z" /> +<glyph unicode="" d="M550 1200h200q21 0 35.5 -14.5t14.5 -35.5v-550h291q21 0 26 -11.5t-8 -27.5l-427 -522q-13 -16 -32 -16t-32 16l-427 522q-13 16 -8 27.5t26 11.5h291v550q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M639 1109l522 -427q16 -13 16 -32t-16 -32l-522 -427q-16 -13 -27.5 -8t-11.5 26v291q-94 -2 -182 -20t-170.5 -52t-147 -92.5t-100.5 -135.5q5 105 27 193.5t67.5 167t113 135t167 91.5t225.5 42v262q0 21 11.5 26t27.5 -8z" /> +<glyph unicode="" d="M850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5zM350 0h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249 q8 7 18 7t18 -7l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5z" /> +<glyph unicode="" d="M1014 1120l106 -106q7 -8 7 -18t-7 -18l-249 -249l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l249 249q8 7 18 7t18 -7zM250 600h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-249 -249q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l249 249l-94 94q-14 14 -10 24.5t25 10.5z" /> +<glyph unicode="" d="M600 1177q117 0 224 -45.5t184.5 -123t123 -184.5t45.5 -224t-45.5 -224t-123 -184.5t-184.5 -123t-224 -45.5t-224 45.5t-184.5 123t-123 184.5t-45.5 224t45.5 224t123 184.5t184.5 123t224 45.5zM704 900h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5 t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM675 400h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M260 1200q9 0 19 -2t15 -4l5 -2q22 -10 44 -23l196 -118q21 -13 36 -24q29 -21 37 -12q11 13 49 35l196 118q22 13 45 23q17 7 38 7q23 0 47 -16.5t37 -33.5l13 -16q14 -21 18 -45l25 -123l8 -44q1 -9 8.5 -14.5t17.5 -5.5h61q10 0 17.5 -7.5t7.5 -17.5v-50 q0 -10 -7.5 -17.5t-17.5 -7.5h-50q-10 0 -17.5 -7.5t-7.5 -17.5v-175h-400v300h-200v-300h-400v175q0 10 -7.5 17.5t-17.5 7.5h-50q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5h61q11 0 18 3t7 8q0 4 9 52l25 128q5 25 19 45q2 3 5 7t13.5 15t21.5 19.5t26.5 15.5 t29.5 7zM915 1079l-166 -162q-7 -7 -5 -12t12 -5h219q10 0 15 7t2 17l-51 149q-3 10 -11 12t-15 -6zM463 917l-177 157q-8 7 -16 5t-11 -12l-51 -143q-3 -10 2 -17t15 -7h231q11 0 12.5 5t-5.5 12zM500 0h-375q-10 0 -17.5 7.5t-7.5 17.5v375h400v-400zM1100 400v-375 q0 -10 -7.5 -17.5t-17.5 -7.5h-375v400h400z" /> +<glyph unicode="" d="M1165 1190q8 3 21 -6.5t13 -17.5q-2 -178 -24.5 -323.5t-55.5 -245.5t-87 -174.5t-102.5 -118.5t-118 -68.5t-118.5 -33t-120 -4.5t-105 9.5t-90 16.5q-61 12 -78 11q-4 1 -12.5 0t-34 -14.5t-52.5 -40.5l-153 -153q-26 -24 -37 -14.5t-11 43.5q0 64 42 102q8 8 50.5 45 t66.5 58q19 17 35 47t13 61q-9 55 -10 102.5t7 111t37 130t78 129.5q39 51 80 88t89.5 63.5t94.5 45t113.5 36t129 31t157.5 37t182 47.5zM1116 1098q-8 9 -22.5 -3t-45.5 -50q-38 -47 -119 -103.5t-142 -89.5l-62 -33q-56 -30 -102 -57t-104 -68t-102.5 -80.5t-85.5 -91 t-64 -104.5q-24 -56 -31 -86t2 -32t31.5 17.5t55.5 59.5q25 30 94 75.5t125.5 77.5t147.5 81q70 37 118.5 69t102 79.5t99 111t86.5 148.5q22 50 24 60t-6 19z" /> +<glyph unicode="" d="M653 1231q-39 -67 -54.5 -131t-10.5 -114.5t24.5 -96.5t47.5 -80t63.5 -62.5t68.5 -46.5t65 -30q-4 7 -17.5 35t-18.5 39.5t-17 39.5t-17 43t-13 42t-9.5 44.5t-2 42t4 43t13.5 39t23 38.5q96 -42 165 -107.5t105 -138t52 -156t13 -159t-19 -149.5q-13 -55 -44 -106.5 t-68 -87t-78.5 -64.5t-72.5 -45t-53 -22q-72 -22 -127 -11q-31 6 -13 19q6 3 17 7q13 5 32.5 21t41 44t38.5 63.5t21.5 81.5t-6.5 94.5t-50 107t-104 115.5q10 -104 -0.5 -189t-37 -140.5t-65 -93t-84 -52t-93.5 -11t-95 24.5q-80 36 -131.5 114t-53.5 171q-2 23 0 49.5 t4.5 52.5t13.5 56t27.5 60t46 64.5t69.5 68.5q-8 -53 -5 -102.5t17.5 -90t34 -68.5t44.5 -39t49 -2q31 13 38.5 36t-4.5 55t-29 64.5t-36 75t-26 75.5q-15 85 2 161.5t53.5 128.5t85.5 92.5t93.5 61t81.5 25.5z" /> +<glyph unicode="" d="M600 1094q82 0 160.5 -22.5t140 -59t116.5 -82.5t94.5 -95t68 -95t42.5 -82.5t14 -57.5t-14 -57.5t-43 -82.5t-68.5 -95t-94.5 -95t-116.5 -82.5t-140 -59t-159.5 -22.5t-159.5 22.5t-140 59t-116.5 82.5t-94.5 95t-68.5 95t-43 82.5t-14 57.5t14 57.5t42.5 82.5t68 95 t94.5 95t116.5 82.5t140 59t160.5 22.5zM888 829q-15 15 -18 12t5 -22q25 -57 25 -119q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 59 23 114q8 19 4.5 22t-17.5 -12q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q22 -36 47 -71t70 -82t92.5 -81t113 -58.5t133.5 -24.5 t133.5 24t113 58.5t92.5 81.5t70 81.5t47 70.5q11 18 9 42.5t-14 41.5q-90 117 -163 189zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l35 34q14 15 12.5 33.5t-16.5 33.5q-44 44 -89 117q-11 18 -28 20t-32 -12z" /> +<glyph unicode="" d="M592 0h-148l31 120q-91 20 -175.5 68.5t-143.5 106.5t-103.5 119t-66.5 110t-22 76q0 21 14 57.5t42.5 82.5t68 95t94.5 95t116.5 82.5t140 59t160.5 22.5q61 0 126 -15l32 121h148zM944 770l47 181q108 -85 176.5 -192t68.5 -159q0 -26 -19.5 -71t-59.5 -102t-93 -112 t-129 -104.5t-158 -75.5l46 173q77 49 136 117t97 131q11 18 9 42.5t-14 41.5q-54 70 -107 130zM310 824q-70 -69 -160 -184q-13 -16 -15 -40.5t9 -42.5q18 -30 39 -60t57 -70.5t74 -73t90 -61t105 -41.5l41 154q-107 18 -178.5 101.5t-71.5 193.5q0 59 23 114q8 19 4.5 22 t-17.5 -12zM448 727l-35 -36q-15 -15 -19.5 -38.5t4.5 -41.5q37 -68 93 -116q16 -13 38.5 -11t36.5 17l12 11l22 86l-3 4q-44 44 -89 117q-11 18 -28 20t-32 -12z" /> +<glyph unicode="" d="M-90 100l642 1066q20 31 48 28.5t48 -35.5l642 -1056q21 -32 7.5 -67.5t-50.5 -35.5h-1294q-37 0 -50.5 34t7.5 66zM155 200h345v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h345l-445 723zM496 700h208q20 0 32 -14.5t8 -34.5l-58 -252 q-4 -20 -21.5 -34.5t-37.5 -14.5h-54q-20 0 -37.5 14.5t-21.5 34.5l-58 252q-4 20 8 34.5t32 14.5z" /> +<glyph unicode="" d="M650 1200q62 0 106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -93 100 -113v-64q0 -21 -13 -29t-32 1l-205 128l-205 -128q-19 -9 -32 -1t-13 29v64q0 20 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5v41 q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44z" /> +<glyph unicode="" d="M850 1200h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-150h-1100v150q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-50h500v50q0 21 14.5 35.5t35.5 14.5zM1100 800v-750q0 -21 -14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v750h1100zM100 600v-100h100v100h-100zM300 600v-100h100v100h-100zM500 600v-100h100v100h-100zM700 600v-100h100v100h-100zM900 600v-100h100v100h-100zM100 400v-100h100v100h-100zM300 400v-100h100v100h-100zM500 400 v-100h100v100h-100zM700 400v-100h100v100h-100zM900 400v-100h100v100h-100zM100 200v-100h100v100h-100zM300 200v-100h100v100h-100zM500 200v-100h100v100h-100zM700 200v-100h100v100h-100zM900 200v-100h100v100h-100z" /> +<glyph unicode="" d="M1135 1165l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-159l-600 -600h-291q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h209l600 600h241v150q0 21 10.5 25t24.5 -10zM522 819l-141 -141l-122 122h-209q-21 0 -35.5 14.5 t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h291zM1135 565l249 -230q15 -14 15 -35t-15 -35l-249 -230q-14 -14 -24.5 -10t-10.5 25v150h-241l-181 181l141 141l122 -122h159v150q0 21 10.5 25t24.5 -10z" /> +<glyph unicode="" d="M100 1100h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5v600q0 41 29.5 70.5t70.5 29.5z" /> +<glyph unicode="" d="M150 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM850 1200h200q21 0 35.5 -14.5t14.5 -35.5v-250h-300v250q0 21 14.5 35.5t35.5 14.5zM1100 800v-300q0 -41 -3 -77.5t-15 -89.5t-32 -96t-58 -89t-89 -77t-129 -51t-174 -20t-174 20 t-129 51t-89 77t-58 89t-32 96t-15 89.5t-3 77.5v300h300v-250v-27v-42.5t1.5 -41t5 -38t10 -35t16.5 -30t25.5 -24.5t35 -19t46.5 -12t60 -4t60 4.5t46.5 12.5t35 19.5t25 25.5t17 30.5t10 35t5 38t2 40.5t-0.5 42v25v250h300z" /> +<glyph unicode="" d="M1100 411l-198 -199l-353 353l-353 -353l-197 199l551 551z" /> +<glyph unicode="" d="M1101 789l-550 -551l-551 551l198 199l353 -353l353 353z" /> +<glyph unicode="" d="M404 1000h746q21 0 35.5 -14.5t14.5 -35.5v-551h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v401h-381zM135 984l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-400h385l215 -200h-750q-21 0 -35.5 14.5 t-14.5 35.5v550h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" /> +<glyph unicode="" d="M56 1200h94q17 0 31 -11t18 -27l38 -162h896q24 0 39 -18.5t10 -42.5l-100 -475q-5 -21 -27 -42.5t-55 -21.5h-633l48 -200h535q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-50q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-300v-50 q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v50h-31q-18 0 -32.5 10t-20.5 19l-5 10l-201 961h-54q-20 0 -35 14.5t-15 35.5t15 35.5t35 14.5z" /> +<glyph unicode="" d="M1200 1000v-100h-1200v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500zM0 800h1200v-800h-1200v800z" /> +<glyph unicode="" d="M200 800l-200 -400v600h200q0 41 29.5 70.5t70.5 29.5h300q42 0 71 -29.5t29 -70.5h500v-200h-1000zM1500 700l-300 -700h-1200l300 700h1200z" /> +<glyph unicode="" d="M635 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-601h150q21 0 25 -10.5t-10 -24.5l-230 -249q-14 -15 -35 -15t-35 15l-230 249q-14 14 -10 24.5t25 10.5h150v601h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" /> +<glyph unicode="" d="M936 864l249 -229q14 -15 14 -35.5t-14 -35.5l-249 -229q-15 -15 -25.5 -10.5t-10.5 24.5v151h-600v-151q0 -20 -10.5 -24.5t-25.5 10.5l-249 229q-14 15 -14 35.5t14 35.5l249 229q15 15 25.5 10.5t10.5 -25.5v-149h600v149q0 21 10.5 25.5t25.5 -10.5z" /> +<glyph unicode="" d="M1169 400l-172 732q-5 23 -23 45.5t-38 22.5h-672q-20 0 -38 -20t-23 -41l-172 -739h1138zM1100 300h-1000q-41 0 -70.5 -29.5t-29.5 -70.5v-100q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v100q0 41 -29.5 70.5t-70.5 29.5zM800 100v100h100v-100h-100 zM1000 100v100h100v-100h-100z" /> +<glyph unicode="" d="M1150 1100q21 0 35.5 -14.5t14.5 -35.5v-850q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v850q0 21 14.5 35.5t35.5 14.5zM1000 200l-675 200h-38l47 -276q3 -16 -5.5 -20t-29.5 -4h-7h-84q-20 0 -34.5 14t-18.5 35q-55 337 -55 351v250v6q0 16 1 23.5t6.5 14 t17.5 6.5h200l675 250v-850zM0 750v-250q-4 0 -11 0.5t-24 6t-30 15t-24 30t-11 48.5v50q0 26 10.5 46t25 30t29 16t25.5 7z" /> +<glyph unicode="" d="M553 1200h94q20 0 29 -10.5t3 -29.5l-18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q19 0 33 -14.5t14 -35t-13 -40.5t-31 -27q-8 -4 -23 -9.5t-65 -19.5t-103 -25t-132.5 -20t-158.5 -9q-57 0 -115 5t-104 12t-88.5 15.5t-73.5 17.5t-54.5 16t-35.5 12l-11 4 q-18 8 -31 28t-13 40.5t14 35t33 14.5h17l118 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3.5 32t28.5 13zM498 110q50 -6 102 -6q53 0 102 6q-12 -49 -39.5 -79.5t-62.5 -30.5t-63 30.5t-39 79.5z" /> +<glyph unicode="" d="M800 946l224 78l-78 -224l234 -45l-180 -155l180 -155l-234 -45l78 -224l-224 78l-45 -234l-155 180l-155 -180l-45 234l-224 -78l78 224l-234 45l180 155l-180 155l234 45l-78 224l224 -78l45 234l155 -180l155 180z" /> +<glyph unicode="" d="M650 1200h50q40 0 70 -40.5t30 -84.5v-150l-28 -125h328q40 0 70 -40.5t30 -84.5v-100q0 -45 -29 -74l-238 -344q-16 -24 -38 -40.5t-45 -16.5h-250q-7 0 -42 25t-66 50l-31 25h-61q-45 0 -72.5 18t-27.5 57v400q0 36 20 63l145 196l96 198q13 28 37.5 48t51.5 20z M650 1100l-100 -212l-150 -213v-375h100l136 -100h214l250 375v125h-450l50 225v175h-50zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1100h250q23 0 45 -16.5t38 -40.5l238 -344q29 -29 29 -74v-100q0 -44 -30 -84.5t-70 -40.5h-328q28 -118 28 -125v-150q0 -44 -30 -84.5t-70 -40.5h-50q-27 0 -51.5 20t-37.5 48l-96 198l-145 196q-20 27 -20 63v400q0 39 27.5 57t72.5 18h61q124 100 139 100z M50 1000h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM636 1000l-136 -100h-100v-375l150 -213l100 -212h50v175l-50 225h450v125l-250 375h-214z" /> +<glyph unicode="" d="M356 873l363 230q31 16 53 -6l110 -112q13 -13 13.5 -32t-11.5 -34l-84 -121h302q84 0 138 -38t54 -110t-55 -111t-139 -39h-106l-131 -339q-6 -21 -19.5 -41t-28.5 -20h-342q-7 0 -90 81t-83 94v525q0 17 14 35.5t28 28.5zM400 792v-503l100 -89h293l131 339 q6 21 19.5 41t28.5 20h203q21 0 30.5 25t0.5 50t-31 25h-456h-7h-6h-5.5t-6 0.5t-5 1.5t-5 2t-4 2.5t-4 4t-2.5 4.5q-12 25 5 47l146 183l-86 83zM50 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v500 q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M475 1103l366 -230q2 -1 6 -3.5t14 -10.5t18 -16.5t14.5 -20t6.5 -22.5v-525q0 -13 -86 -94t-93 -81h-342q-15 0 -28.5 20t-19.5 41l-131 339h-106q-85 0 -139.5 39t-54.5 111t54 110t138 38h302l-85 121q-11 15 -10.5 34t13.5 32l110 112q22 22 53 6zM370 945l146 -183 q17 -22 5 -47q-2 -2 -3.5 -4.5t-4 -4t-4 -2.5t-5 -2t-5 -1.5t-6 -0.5h-6h-6.5h-6h-475v-100h221q15 0 29 -20t20 -41l130 -339h294l106 89v503l-342 236zM1050 800h100q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5 v500q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M550 1294q72 0 111 -55t39 -139v-106l339 -131q21 -6 41 -19.5t20 -28.5v-342q0 -7 -81 -90t-94 -83h-525q-17 0 -35.5 14t-28.5 28l-9 14l-230 363q-16 31 6 53l112 110q13 13 32 13.5t34 -11.5l121 -84v302q0 84 38 138t110 54zM600 972v203q0 21 -25 30.5t-50 0.5 t-25 -31v-456v-7v-6v-5.5t-0.5 -6t-1.5 -5t-2 -5t-2.5 -4t-4 -4t-4.5 -2.5q-25 -12 -47 5l-183 146l-83 -86l236 -339h503l89 100v293l-339 131q-21 6 -41 19.5t-20 28.5zM450 200h500q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-500 q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M350 1100h500q21 0 35.5 14.5t14.5 35.5v100q0 21 -14.5 35.5t-35.5 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100q0 -21 14.5 -35.5t35.5 -14.5zM600 306v-106q0 -84 -39 -139t-111 -55t-110 54t-38 138v302l-121 -84q-15 -12 -34 -11.5t-32 13.5l-112 110 q-22 22 -6 53l230 363q1 2 3.5 6t10.5 13.5t16.5 17t20 13.5t22.5 6h525q13 0 94 -83t81 -90v-342q0 -15 -20 -28.5t-41 -19.5zM308 900l-236 -339l83 -86l183 146q22 17 47 5q2 -1 4.5 -2.5t4 -4t2.5 -4t2 -5t1.5 -5t0.5 -6v-5.5v-6v-7v-456q0 -22 25 -31t50 0.5t25 30.5 v203q0 15 20 28.5t41 19.5l339 131v293l-89 100h-503z" /> +<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM914 632l-275 223q-16 13 -27.5 8t-11.5 -26v-137h-275 q-10 0 -17.5 -7.5t-7.5 -17.5v-150q0 -10 7.5 -17.5t17.5 -7.5h275v-137q0 -21 11.5 -26t27.5 8l275 223q16 13 16 32t-16 32z" /> +<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM561 855l-275 -223q-16 -13 -16 -32t16 -32l275 -223q16 -13 27.5 -8 t11.5 26v137h275q10 0 17.5 7.5t7.5 17.5v150q0 10 -7.5 17.5t-17.5 7.5h-275v137q0 21 -11.5 26t-27.5 -8z" /> +<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM855 639l-223 275q-13 16 -32 16t-32 -16l-223 -275q-13 -16 -8 -27.5 t26 -11.5h137v-275q0 -10 7.5 -17.5t17.5 -7.5h150q10 0 17.5 7.5t7.5 17.5v275h137q21 0 26 11.5t-8 27.5z" /> +<glyph unicode="" d="M600 1178q118 0 225 -45.5t184.5 -123t123 -184.5t45.5 -225t-45.5 -225t-123 -184.5t-184.5 -123t-225 -45.5t-225 45.5t-184.5 123t-123 184.5t-45.5 225t45.5 225t123 184.5t184.5 123t225 45.5zM675 900h-150q-10 0 -17.5 -7.5t-7.5 -17.5v-275h-137q-21 0 -26 -11.5 t8 -27.5l223 -275q13 -16 32 -16t32 16l223 275q13 16 8 27.5t-26 11.5h-137v275q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M600 1176q116 0 222.5 -46t184 -123.5t123.5 -184t46 -222.5t-46 -222.5t-123.5 -184t-184 -123.5t-222.5 -46t-222.5 46t-184 123.5t-123.5 184t-46 222.5t46 222.5t123.5 184t184 123.5t222.5 46zM627 1101q-15 -12 -36.5 -20.5t-35.5 -12t-43 -8t-39 -6.5 q-15 -3 -45.5 0t-45.5 -2q-20 -7 -51.5 -26.5t-34.5 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -91t-29.5 -79q-9 -34 5 -93t8 -87q0 -9 17 -44.5t16 -59.5q12 0 23 -5t23.5 -15t19.5 -14q16 -8 33 -15t40.5 -15t34.5 -12q21 -9 52.5 -32t60 -38t57.5 -11 q7 -15 -3 -34t-22.5 -40t-9.5 -38q13 -21 23 -34.5t27.5 -27.5t36.5 -18q0 -7 -3.5 -16t-3.5 -14t5 -17q104 -2 221 112q30 29 46.5 47t34.5 49t21 63q-13 8 -37 8.5t-36 7.5q-15 7 -49.5 15t-51.5 19q-18 0 -41 -0.5t-43 -1.5t-42 -6.5t-38 -16.5q-51 -35 -66 -12 q-4 1 -3.5 25.5t0.5 25.5q-6 13 -26.5 17.5t-24.5 6.5q1 15 -0.5 30.5t-7 28t-18.5 11.5t-31 -21q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q7 -12 18 -24t21.5 -20.5t20 -15t15.5 -10.5l5 -3q2 12 7.5 30.5t8 34.5t-0.5 32q-3 18 3.5 29 t18 22.5t15.5 24.5q6 14 10.5 35t8 31t15.5 22.5t34 22.5q-6 18 10 36q8 0 24 -1.5t24.5 -1.5t20 4.5t20.5 15.5q-10 23 -31 42.5t-37.5 29.5t-49 27t-43.5 23q0 1 2 8t3 11.5t1.5 10.5t-1 9.5t-4.5 4.5q31 -13 58.5 -14.5t38.5 2.5l12 5q5 28 -9.5 46t-36.5 24t-50 15 t-41 20q-18 -4 -37 0zM613 994q0 -17 8 -42t17 -45t9 -23q-8 1 -39.5 5.5t-52.5 10t-37 16.5q3 11 16 29.5t16 25.5q10 -10 19 -10t14 6t13.5 14.5t16.5 12.5z" /> +<glyph unicode="" d="M756 1157q164 92 306 -9l-259 -138l145 -232l251 126q6 -89 -34 -156.5t-117 -110.5q-60 -34 -127 -39.5t-126 16.5l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5t15 37.5l600 599q-34 101 5.5 201.5t135.5 154.5z" /> +<glyph unicode="" horiz-adv-x="1220" d="M100 1196h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 1096h-200v-100h200v100zM100 796h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 696h-500v-100h500v100zM100 396h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5v100q0 41 29.5 70.5t70.5 29.5zM1100 296h-300v-100h300v100z " /> +<glyph unicode="" d="M150 1200h900q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM700 500v-300l-200 -200v500l-350 500h900z" /> +<glyph unicode="" d="M500 1200h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5zM500 1100v-100h200v100h-200zM1200 400v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5v200h1200z" /> +<glyph unicode="" d="M50 1200h300q21 0 25 -10.5t-10 -24.5l-94 -94l199 -199q7 -8 7 -18t-7 -18l-106 -106q-8 -7 -18 -7t-18 7l-199 199l-94 -94q-14 -14 -24.5 -10t-10.5 25v300q0 21 14.5 35.5t35.5 14.5zM850 1200h300q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -10.5 -25t-24.5 10l-94 94 l-199 -199q-8 -7 -18 -7t-18 7l-106 106q-7 8 -7 18t7 18l199 199l-94 94q-14 14 -10 24.5t25 10.5zM364 470l106 -106q7 -8 7 -18t-7 -18l-199 -199l94 -94q14 -14 10 -24.5t-25 -10.5h-300q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 10.5 25t24.5 -10l94 -94l199 199 q8 7 18 7t18 -7zM1071 271l94 94q14 14 24.5 10t10.5 -25v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -25 10.5t10 24.5l94 94l-199 199q-7 8 -7 18t7 18l106 106q8 7 18 7t18 -7z" /> +<glyph unicode="" d="M596 1192q121 0 231.5 -47.5t190 -127t127 -190t47.5 -231.5t-47.5 -231.5t-127 -190.5t-190 -127t-231.5 -47t-231.5 47t-190.5 127t-127 190.5t-47 231.5t47 231.5t127 190t190.5 127t231.5 47.5zM596 1010q-112 0 -207.5 -55.5t-151 -151t-55.5 -207.5t55.5 -207.5 t151 -151t207.5 -55.5t207.5 55.5t151 151t55.5 207.5t-55.5 207.5t-151 151t-207.5 55.5zM454.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38.5 -16.5t-38.5 16.5t-16 39t16 38.5t38.5 16zM754.5 905q22.5 0 38.5 -16t16 -38.5t-16 -39t-38 -16.5q-14 0 -29 10l-55 -145 q17 -23 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 23 16 39t38.5 16zM345.5 709q22.5 0 38.5 -16t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16zM854.5 709q22.5 0 38.5 -16 t16 -38.5t-16 -38.5t-38.5 -16t-38.5 16t-16 38.5t16 38.5t38.5 16z" /> +<glyph unicode="" d="M546 173l469 470q91 91 99 192q7 98 -52 175.5t-154 94.5q-22 4 -47 4q-34 0 -66.5 -10t-56.5 -23t-55.5 -38t-48 -41.5t-48.5 -47.5q-376 -375 -391 -390q-30 -27 -45 -41.5t-37.5 -41t-32 -46.5t-16 -47.5t-1.5 -56.5q9 -62 53.5 -95t99.5 -33q74 0 125 51l548 548 q36 36 20 75q-7 16 -21.5 26t-32.5 10q-26 0 -50 -23q-13 -12 -39 -38l-341 -338q-15 -15 -35.5 -15.5t-34.5 13.5t-14 34.5t14 34.5q327 333 361 367q35 35 67.5 51.5t78.5 16.5q14 0 29 -1q44 -8 74.5 -35.5t43.5 -68.5q14 -47 2 -96.5t-47 -84.5q-12 -11 -32 -32 t-79.5 -81t-114.5 -115t-124.5 -123.5t-123 -119.5t-96.5 -89t-57 -45q-56 -27 -120 -27q-70 0 -129 32t-93 89q-48 78 -35 173t81 163l511 511q71 72 111 96q91 55 198 55q80 0 152 -33q78 -36 129.5 -103t66.5 -154q17 -93 -11 -183.5t-94 -156.5l-482 -476 q-15 -15 -36 -16t-37 14t-17.5 34t14.5 35z" /> +<glyph unicode="" d="M649 949q48 68 109.5 104t121.5 38.5t118.5 -20t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-150 152.5t-126.5 127.5t-93.5 124.5t-33.5 117.5q0 64 28 123t73 100.5t104 64t119 20 t120.5 -38.5t104.5 -104zM896 972q-33 0 -64.5 -19t-56.5 -46t-47.5 -53.5t-43.5 -45.5t-37.5 -19t-36 19t-40 45.5t-43 53.5t-54 46t-65.5 19q-67 0 -122.5 -55.5t-55.5 -132.5q0 -23 13.5 -51t46 -65t57.5 -63t76 -75l22 -22q15 -14 44 -44t50.5 -51t46 -44t41 -35t23 -12 t23.5 12t42.5 36t46 44t52.5 52t44 43q4 4 12 13q43 41 63.5 62t52 55t46 55t26 46t11.5 44q0 79 -53 133.5t-120 54.5z" /> +<glyph unicode="" d="M776.5 1214q93.5 0 159.5 -66l141 -141q66 -66 66 -160q0 -42 -28 -95.5t-62 -87.5l-29 -29q-31 53 -77 99l-18 18l95 95l-247 248l-389 -389l212 -212l-105 -106l-19 18l-141 141q-66 66 -66 159t66 159l283 283q65 66 158.5 66zM600 706l105 105q10 -8 19 -17l141 -141 q66 -66 66 -159t-66 -159l-283 -283q-66 -66 -159 -66t-159 66l-141 141q-66 66 -66 159.5t66 159.5l55 55q29 -55 75 -102l18 -17l-95 -95l247 -248l389 389z" /> +<glyph unicode="" d="M603 1200q85 0 162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5v953q0 21 30 46.5t81 48t129 37.5t163 15zM300 1000v-700h600v700h-600zM600 254q-43 0 -73.5 -30.5t-30.5 -73.5t30.5 -73.5t73.5 -30.5t73.5 30.5 t30.5 73.5t-30.5 73.5t-73.5 30.5z" /> +<glyph unicode="" d="M902 1185l283 -282q15 -15 15 -36t-14.5 -35.5t-35.5 -14.5t-35 15l-36 35l-279 -267v-300l-212 210l-308 -307l-280 -203l203 280l307 308l-210 212h300l267 279l-35 36q-15 14 -15 35t14.5 35.5t35.5 14.5t35 -15z" /> +<glyph unicode="" d="M700 1248v-78q38 -5 72.5 -14.5t75.5 -31.5t71 -53.5t52 -84t24 -118.5h-159q-4 36 -10.5 59t-21 45t-40 35.5t-64.5 20.5v-307l64 -13q34 -7 64 -16.5t70 -32t67.5 -52.5t47.5 -80t20 -112q0 -139 -89 -224t-244 -97v-77h-100v79q-150 16 -237 103q-40 40 -52.5 93.5 t-15.5 139.5h139q5 -77 48.5 -126t117.5 -65v335l-27 8q-46 14 -79 26.5t-72 36t-63 52t-40 72.5t-16 98q0 70 25 126t67.5 92t94.5 57t110 27v77h100zM600 754v274q-29 -4 -50 -11t-42 -21.5t-31.5 -41.5t-10.5 -65q0 -29 7 -50.5t16.5 -34t28.5 -22.5t31.5 -14t37.5 -10 q9 -3 13 -4zM700 547v-310q22 2 42.5 6.5t45 15.5t41.5 27t29 42t12 59.5t-12.5 59.5t-38 44.5t-53 31t-66.5 24.5z" /> +<glyph unicode="" d="M561 1197q84 0 160.5 -40t123.5 -109.5t47 -147.5h-153q0 40 -19.5 71.5t-49.5 48.5t-59.5 26t-55.5 9q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -26 13.5 -63t26.5 -61t37 -66q6 -9 9 -14h241v-100h-197q8 -50 -2.5 -115t-31.5 -95q-45 -62 -99 -112 q34 10 83 17.5t71 7.5q32 1 102 -16t104 -17q83 0 136 30l50 -147q-31 -19 -58 -30.5t-55 -15.5t-42 -4.5t-46 -0.5q-23 0 -76 17t-111 32.5t-96 11.5q-39 -3 -82 -16t-67 -25l-23 -11l-55 145q4 3 16 11t15.5 10.5t13 9t15.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221v100h166q-23 47 -44 104q-7 20 -12 41.5t-6 55.5t6 66.5t29.5 70.5t58.5 71q97 88 263 88z" /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM935 1184l230 -249q14 -14 10 -24.5t-25 -10.5h-150v-900h-200v900h-150q-21 0 -25 10.5t10 24.5l230 249q14 15 35 15t35 -15z" /> +<glyph unicode="" d="M1000 700h-100v100h-100v-100h-100v500h300v-500zM400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM801 1100v-200h100v200h-100zM1000 350l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150z " /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 1050l-200 -250h200v-100h-300v150l200 250h-200v100h300v-150zM1000 0h-100v100h-100v-100h-100v500h300v-500zM801 400v-200h100v200h-100z " /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1000 700h-100v400h-100v100h200v-500zM1100 0h-100v100h-200v400h300v-500zM901 400v-200h100v200h-100z" /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1100 700h-100v100h-200v400h300v-500zM901 1100v-200h100v200h-100zM1000 0h-100v400h-100v100h200v-500z" /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM900 1000h-200v200h200v-200zM1000 700h-300v200h300v-200zM1100 400h-400v200h400v-200zM1200 100h-500v200h500v-200z" /> +<glyph unicode="" d="M400 300h150q21 0 25 -11t-10 -25l-230 -250q-14 -15 -35 -15t-35 15l-230 250q-14 14 -10 25t25 11h150v900h200v-900zM1200 1000h-500v200h500v-200zM1100 700h-400v200h400v-200zM1000 400h-300v200h300v-200zM900 100h-200v200h200v-200z" /> +<glyph unicode="" d="M350 1100h400q162 0 256 -93.5t94 -256.5v-400q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5z" /> +<glyph unicode="" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-163 0 -256.5 92.5t-93.5 257.5v400q0 163 94 256.5t256 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM440 770l253 -190q17 -12 17 -30t-17 -30l-253 -190q-16 -12 -28 -6.5t-12 26.5v400q0 21 12 26.5t28 -6.5z" /> +<glyph unicode="" d="M350 1100h400q163 0 256.5 -94t93.5 -256v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 163 92.5 256.5t257.5 93.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM350 700h400q21 0 26.5 -12t-6.5 -28l-190 -253q-12 -17 -30 -17t-30 17l-190 253q-12 16 -6.5 28t26.5 12z" /> +<glyph unicode="" d="M350 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -163 -92.5 -256.5t-257.5 -93.5h-400q-163 0 -256.5 94t-93.5 256v400q0 165 92.5 257.5t257.5 92.5zM800 900h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5 v500q0 41 -29.5 70.5t-70.5 29.5zM580 693l190 -253q12 -16 6.5 -28t-26.5 -12h-400q-21 0 -26.5 12t6.5 28l190 253q12 17 30 17t30 -17z" /> +<glyph unicode="" d="M550 1100h400q165 0 257.5 -92.5t92.5 -257.5v-400q0 -165 -92.5 -257.5t-257.5 -92.5h-400q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h450q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-450q-21 0 -35.5 14.5t-14.5 35.5v100 q0 21 14.5 35.5t35.5 14.5zM338 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" /> +<glyph unicode="" d="M793 1182l9 -9q8 -10 5 -27q-3 -11 -79 -225.5t-78 -221.5l300 1q24 0 32.5 -17.5t-5.5 -35.5q-1 0 -133.5 -155t-267 -312.5t-138.5 -162.5q-12 -15 -26 -15h-9l-9 8q-9 11 -4 32q2 9 42 123.5t79 224.5l39 110h-302q-23 0 -31 19q-10 21 6 41q75 86 209.5 237.5 t228 257t98.5 111.5q9 16 25 16h9z" /> +<glyph unicode="" d="M350 1100h400q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-450q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h450q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400 q0 165 92.5 257.5t257.5 92.5zM938 867l324 -284q16 -14 16 -33t-16 -33l-324 -284q-16 -14 -27 -9t-11 26v150h-250q-21 0 -35.5 14.5t-14.5 35.5v200q0 21 14.5 35.5t35.5 14.5h250v150q0 21 11 26t27 -9z" /> +<glyph unicode="" d="M750 1200h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -10.5 -25t-24.5 10l-109 109l-312 -312q-15 -15 -35.5 -15t-35.5 15l-141 141q-15 15 -15 35.5t15 35.5l312 312l-109 109q-14 14 -10 24.5t25 10.5zM456 900h-156q-41 0 -70.5 -29.5t-29.5 -70.5v-500 q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v148l200 200v-298q0 -165 -93.5 -257.5t-256.5 -92.5h-400q-165 0 -257.5 92.5t-92.5 257.5v400q0 165 92.5 257.5t257.5 92.5h300z" /> +<glyph unicode="" d="M600 1186q119 0 227.5 -46.5t187 -125t125 -187t46.5 -227.5t-46.5 -227.5t-125 -187t-187 -125t-227.5 -46.5t-227.5 46.5t-187 125t-125 187t-46.5 227.5t46.5 227.5t125 187t187 125t227.5 46.5zM600 1022q-115 0 -212 -56.5t-153.5 -153.5t-56.5 -212t56.5 -212 t153.5 -153.5t212 -56.5t212 56.5t153.5 153.5t56.5 212t-56.5 212t-153.5 153.5t-212 56.5zM600 794q80 0 137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137t57 137t137 57z" /> +<glyph unicode="" d="M450 1200h200q21 0 35.5 -14.5t14.5 -35.5v-350h245q20 0 25 -11t-9 -26l-383 -426q-14 -15 -33.5 -15t-32.5 15l-379 426q-13 15 -8.5 26t25.5 11h250v350q0 21 14.5 35.5t35.5 14.5zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" /> +<glyph unicode="" d="M583 1182l378 -435q14 -15 9 -31t-26 -16h-244v-250q0 -20 -17 -35t-39 -15h-200q-20 0 -32 14.5t-12 35.5v250h-250q-20 0 -25.5 16.5t8.5 31.5l383 431q14 16 33.5 17t33.5 -14zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5z M900 200v-50h100v50h-100z" /> +<glyph unicode="" d="M396 723l369 369q7 7 17.5 7t17.5 -7l139 -139q7 -8 7 -18.5t-7 -17.5l-525 -525q-7 -8 -17.5 -8t-17.5 8l-292 291q-7 8 -7 18t7 18l139 139q8 7 18.5 7t17.5 -7zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50 h-100z" /> +<glyph unicode="" d="M135 1023l142 142q14 14 35 14t35 -14l77 -77l-212 -212l-77 76q-14 15 -14 36t14 35zM655 855l210 210q14 14 24.5 10t10.5 -25l-2 -599q-1 -20 -15.5 -35t-35.5 -15l-597 -1q-21 0 -25 10.5t10 24.5l208 208l-154 155l212 212zM50 300h1000q21 0 35.5 -14.5t14.5 -35.5 v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" /> +<glyph unicode="" d="M350 1200l599 -2q20 -1 35 -15.5t15 -35.5l1 -597q0 -21 -10.5 -25t-24.5 10l-208 208l-155 -154l-212 212l155 154l-210 210q-14 14 -10 24.5t25 10.5zM524 512l-76 -77q-15 -14 -36 -14t-35 14l-142 142q-14 14 -14 35t14 35l77 77zM50 300h1000q21 0 35.5 -14.5 t14.5 -35.5v-250h-1100v250q0 21 14.5 35.5t35.5 14.5zM900 200v-50h100v50h-100z" /> +<glyph unicode="" d="M1200 103l-483 276l-314 -399v423h-399l1196 796v-1096zM483 424v-230l683 953z" /> +<glyph unicode="" d="M1100 1000v-850q0 -21 -14.5 -35.5t-35.5 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200z" /> +<glyph unicode="" d="M1100 1000l-2 -149l-299 -299l-95 95q-9 9 -21.5 9t-21.5 -9l-149 -147h-312v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1132 638l106 -106q7 -7 7 -17.5t-7 -17.5l-420 -421q-8 -7 -18 -7 t-18 7l-202 203q-8 7 -8 17.5t8 17.5l106 106q7 8 17.5 8t17.5 -8l79 -79l297 297q7 7 17.5 7t17.5 -7z" /> +<glyph unicode="" d="M1100 1000v-269l-103 -103l-134 134q-15 15 -33.5 16.5t-34.5 -12.5l-266 -266h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM1202 572l70 -70q15 -15 15 -35.5t-15 -35.5l-131 -131 l131 -131q15 -15 15 -35.5t-15 -35.5l-70 -70q-15 -15 -35.5 -15t-35.5 15l-131 131l-131 -131q-15 -15 -35.5 -15t-35.5 15l-70 70q-15 15 -15 35.5t15 35.5l131 131l-131 131q-15 15 -15 35.5t15 35.5l70 70q15 15 35.5 15t35.5 -15l131 -131l131 131q15 15 35.5 15 t35.5 -15z" /> +<glyph unicode="" d="M1100 1000v-300h-350q-21 0 -35.5 -14.5t-14.5 -35.5v-150h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM850 600h100q21 0 35.5 -14.5t14.5 -35.5v-250h150q21 0 25 -10.5t-10 -24.5 l-230 -230q-14 -14 -35 -14t-35 14l-230 230q-14 14 -10 24.5t25 10.5h150v250q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M1100 1000v-400l-165 165q-14 15 -35 15t-35 -15l-263 -265h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100zM700 1000h-100v200h100v-200zM935 565l230 -229q14 -15 10 -25.5t-25 -10.5h-150v-250q0 -20 -14.5 -35 t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35v250h-150q-21 0 -25 10.5t10 25.5l230 229q14 15 35 15t35 -15z" /> +<glyph unicode="" d="M50 1100h1100q21 0 35.5 -14.5t14.5 -35.5v-150h-1200v150q0 21 14.5 35.5t35.5 14.5zM1200 800v-550q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v550h1200zM100 500v-200h400v200h-400z" /> +<glyph unicode="" d="M935 1165l248 -230q14 -14 14 -35t-14 -35l-248 -230q-14 -14 -24.5 -10t-10.5 25v150h-400v200h400v150q0 21 10.5 25t24.5 -10zM200 800h-50q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v-200zM400 800h-100v200h100v-200zM18 435l247 230 q14 14 24.5 10t10.5 -25v-150h400v-200h-400v-150q0 -21 -10.5 -25t-24.5 10l-247 230q-15 14 -15 35t15 35zM900 300h-100v200h100v-200zM1000 500h51q20 0 34.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-34.5 -14.5h-51v200z" /> +<glyph unicode="" d="M862 1073l276 116q25 18 43.5 8t18.5 -41v-1106q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v397q-4 1 -11 5t-24 17.5t-30 29t-24 42t-11 56.5v359q0 31 18.5 65t43.5 52zM550 1200q22 0 34.5 -12.5t14.5 -24.5l1 -13v-450q0 -28 -10.5 -59.5 t-25 -56t-29 -45t-25.5 -31.5l-10 -11v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447q-4 4 -11 11.5t-24 30.5t-30 46t-24 55t-11 60v450q0 2 0.5 5.5t4 12t8.5 15t14.5 12t22.5 5.5q20 0 32.5 -12.5t14.5 -24.5l3 -13v-350h100v350v5.5t2.5 12 t7 15t15 12t25.5 5.5q23 0 35.5 -12.5t13.5 -24.5l1 -13v-350h100v350q0 2 0.5 5.5t3 12t7 15t15 12t24.5 5.5z" /> +<glyph unicode="" d="M1200 1100v-56q-4 0 -11 -0.5t-24 -3t-30 -7.5t-24 -15t-11 -24v-888q0 -22 25 -34.5t50 -13.5l25 -2v-56h-400v56q75 0 87.5 6.5t12.5 43.5v394h-500v-394q0 -37 12.5 -43.5t87.5 -6.5v-56h-400v56q4 0 11 0.5t24 3t30 7.5t24 15t11 24v888q0 22 -25 34.5t-50 13.5 l-25 2v56h400v-56q-75 0 -87.5 -6.5t-12.5 -43.5v-394h500v394q0 37 -12.5 43.5t-87.5 6.5v56h400z" /> +<glyph unicode="" d="M675 1000h375q21 0 35.5 -14.5t14.5 -35.5v-150h-105l-295 -98v98l-200 200h-400l100 100h375zM100 900h300q41 0 70.5 -29.5t29.5 -70.5v-500q0 -41 -29.5 -70.5t-70.5 -29.5h-300q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5zM100 800v-200h300v200 h-300zM1100 535l-400 -133v163l400 133v-163zM100 500v-200h300v200h-300zM1100 398v-248q0 -21 -14.5 -35.5t-35.5 -14.5h-375l-100 -100h-375l-100 100h400l200 200h105z" /> +<glyph unicode="" d="M17 1007l162 162q17 17 40 14t37 -22l139 -194q14 -20 11 -44.5t-20 -41.5l-119 -118q102 -142 228 -268t267 -227l119 118q17 17 42.5 19t44.5 -12l192 -136q19 -14 22.5 -37.5t-13.5 -40.5l-163 -162q-3 -1 -9.5 -1t-29.5 2t-47.5 6t-62.5 14.5t-77.5 26.5t-90 42.5 t-101.5 60t-111 83t-119 108.5q-74 74 -133.5 150.5t-94.5 138.5t-60 119.5t-34.5 100t-15 74.5t-4.5 48z" /> +<glyph unicode="" d="M600 1100q92 0 175 -10.5t141.5 -27t108.5 -36.5t81.5 -40t53.5 -37t31 -27l9 -10v-200q0 -21 -14.5 -33t-34.5 -9l-202 34q-20 3 -34.5 20t-14.5 38v146q-141 24 -300 24t-300 -24v-146q0 -21 -14.5 -38t-34.5 -20l-202 -34q-20 -3 -34.5 9t-14.5 33v200q3 4 9.5 10.5 t31 26t54 37.5t80.5 39.5t109 37.5t141 26.5t175 10.5zM600 795q56 0 97 -9.5t60 -23.5t30 -28t12 -24l1 -10v-50l365 -303q14 -15 24.5 -40t10.5 -45v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v212q0 20 10.5 45t24.5 40l365 303v50 q0 4 1 10.5t12 23t30 29t60 22.5t97 10z" /> +<glyph unicode="" d="M1100 700l-200 -200h-600l-200 200v500h200v-200h200v200h200v-200h200v200h200v-500zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5 t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M700 1100h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-1000h300v1000q0 41 -29.5 70.5t-70.5 29.5zM1100 800h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-700h300v700q0 41 -29.5 70.5t-70.5 29.5zM400 0h-300v400q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-400z " /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 300h-100v200h-100v-200h-100v500h100v-200h100v200h100v-500zM900 700v-300l-100 -100h-200v500h200z M700 700v-300h100v300h-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-300h200v-100h-300v500h300v-100zM900 700h-200v-300h200v-100h-300v500h300v-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 400l-300 150l300 150v-300zM900 550l-300 -150v300z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM900 300h-700v500h700v-500zM800 700h-130q-38 0 -66.5 -43t-28.5 -108t27 -107t68 -42h130v300zM300 700v-300 h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 700h-200v-100h200v-300h-300v100h200v100h-200v300h300v-100zM900 300h-100v400h-100v100h200v-500z M700 300h-100v100h100v-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM300 700h200v-400h-300v500h100v-100zM900 300h-100v400h-100v100h200v-500zM300 600v-200h100v200h-100z M700 300h-100v100h100v-100z" /> +<glyph unicode="" d="M200 1100h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212v500q0 124 88 212t212 88zM100 900v-700h900v700h-900zM500 500l-199 -200h-100v50l199 200v150h-200v100h300v-300zM900 300h-100v400h-100v100h200v-500zM701 300h-100 v100h100v-100z" /> +<glyph unicode="" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700h-300v-200h300v-100h-300l-100 100v200l100 100h300v-100z" /> +<glyph unicode="" d="M600 1191q120 0 229.5 -47t188.5 -126t126 -188.5t47 -229.5t-47 -229.5t-126 -188.5t-188.5 -126t-229.5 -47t-229.5 47t-188.5 126t-126 188.5t-47 229.5t47 229.5t126 188.5t188.5 126t229.5 47zM600 1021q-114 0 -211 -56.5t-153.5 -153.5t-56.5 -211t56.5 -211 t153.5 -153.5t211 -56.5t211 56.5t153.5 153.5t56.5 211t-56.5 211t-153.5 153.5t-211 56.5zM800 700v-100l-50 -50l100 -100v-50h-100l-100 100h-150v-100h-100v400h300zM500 700v-100h200v100h-200z" /> +<glyph unicode="" d="M503 1089q110 0 200.5 -59.5t134.5 -156.5q44 14 90 14q120 0 205 -86.5t85 -207t-85 -207t-205 -86.5h-128v250q0 21 -14.5 35.5t-35.5 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-250h-222q-80 0 -136 57.5t-56 136.5q0 69 43 122.5t108 67.5q-2 19 -2 37q0 100 49 185 t134 134t185 49zM525 500h150q10 0 17.5 -7.5t7.5 -17.5v-275h137q21 0 26 -11.5t-8 -27.5l-223 -244q-13 -16 -32 -16t-32 16l-223 244q-13 16 -8 27.5t26 11.5h137v275q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M502 1089q110 0 201 -59.5t135 -156.5q43 15 89 15q121 0 206 -86.5t86 -206.5q0 -99 -60 -181t-150 -110l-378 360q-13 16 -31.5 16t-31.5 -16l-381 -365h-9q-79 0 -135.5 57.5t-56.5 136.5q0 69 43 122.5t108 67.5q-2 19 -2 38q0 100 49 184.5t133.5 134t184.5 49.5z M632 467l223 -228q13 -16 8 -27.5t-26 -11.5h-137v-275q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v275h-137q-21 0 -26 11.5t8 27.5q199 204 223 228q19 19 31.5 19t32.5 -19z" /> +<glyph unicode="" d="M700 100v100h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170l-270 -300h400v-100h-50q-21 0 -35.5 -14.5t-14.5 -35.5v-50h400v50q0 21 -14.5 35.5t-35.5 14.5h-50z" /> +<glyph unicode="" d="M600 1179q94 0 167.5 -56.5t99.5 -145.5q89 -6 150.5 -71.5t61.5 -155.5q0 -61 -29.5 -112.5t-79.5 -82.5q9 -29 9 -55q0 -74 -52.5 -126.5t-126.5 -52.5q-55 0 -100 30v-251q21 0 35.5 -14.5t14.5 -35.5v-50h-300v50q0 21 14.5 35.5t35.5 14.5v251q-45 -30 -100 -30 q-74 0 -126.5 52.5t-52.5 126.5q0 18 4 38q-47 21 -75.5 65t-28.5 97q0 74 52.5 126.5t126.5 52.5q5 0 23 -2q0 2 -1 10t-1 13q0 116 81.5 197.5t197.5 81.5z" /> +<glyph unicode="" d="M1010 1010q111 -111 150.5 -260.5t0 -299t-150.5 -260.5q-83 -83 -191.5 -126.5t-218.5 -43.5t-218.5 43.5t-191.5 126.5q-111 111 -150.5 260.5t0 299t150.5 260.5q83 83 191.5 126.5t218.5 43.5t218.5 -43.5t191.5 -126.5zM476 1065q-4 0 -8 -1q-121 -34 -209.5 -122.5 t-122.5 -209.5q-4 -12 2.5 -23t18.5 -14l36 -9q3 -1 7 -1q23 0 29 22q27 96 98 166q70 71 166 98q11 3 17.5 13.5t3.5 22.5l-9 35q-3 13 -14 19q-7 4 -15 4zM512 920q-4 0 -9 -2q-80 -24 -138.5 -82.5t-82.5 -138.5q-4 -13 2 -24t19 -14l34 -9q4 -1 8 -1q22 0 28 21 q18 58 58.5 98.5t97.5 58.5q12 3 18 13.5t3 21.5l-9 35q-3 12 -14 19q-7 4 -15 4zM719.5 719.5q-49.5 49.5 -119.5 49.5t-119.5 -49.5t-49.5 -119.5t49.5 -119.5t119.5 -49.5t119.5 49.5t49.5 119.5t-49.5 119.5zM855 551q-22 0 -28 -21q-18 -58 -58.5 -98.5t-98.5 -57.5 q-11 -4 -17 -14.5t-3 -21.5l9 -35q3 -12 14 -19q7 -4 15 -4q4 0 9 2q80 24 138.5 82.5t82.5 138.5q4 13 -2.5 24t-18.5 14l-34 9q-4 1 -8 1zM1000 515q-23 0 -29 -22q-27 -96 -98 -166q-70 -71 -166 -98q-11 -3 -17.5 -13.5t-3.5 -22.5l9 -35q3 -13 14 -19q7 -4 15 -4 q4 0 8 1q121 34 209.5 122.5t122.5 209.5q4 12 -2.5 23t-18.5 14l-36 9q-3 1 -7 1z" /> +<glyph unicode="" d="M700 800h300v-380h-180v200h-340v-200h-380v755q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM700 300h162l-212 -212l-212 212h162v200h100v-200zM520 0h-395q-10 0 -17.5 7.5t-7.5 17.5v395zM1000 220v-195q0 -10 -7.5 -17.5t-17.5 -7.5h-195z" /> +<glyph unicode="" d="M700 800h300v-520l-350 350l-550 -550v1095q0 10 7.5 17.5t17.5 7.5h575v-400zM1000 900h-200v200zM862 200h-162v-200h-100v200h-162l212 212zM480 0h-355q-10 0 -17.5 7.5t-7.5 17.5v55h380v-80zM1000 80v-55q0 -10 -7.5 -17.5t-17.5 -7.5h-155v80h180z" /> +<glyph unicode="" d="M1162 800h-162v-200h100l100 -100h-300v300h-162l212 212zM200 800h200q27 0 40 -2t29.5 -10.5t23.5 -30t7 -57.5h300v-100h-600l-200 -350v450h100q0 36 7 57.5t23.5 30t29.5 10.5t40 2zM800 400h240l-240 -400h-800l300 500h500v-100z" /> +<glyph unicode="" d="M650 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM1000 850v150q41 0 70.5 -29.5t29.5 -70.5v-800 q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-1 0 -20 4l246 246l-326 326v324q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM412 250l-212 -212v162h-200v100h200v162z" /> +<glyph unicode="" d="M450 1100h100q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-300q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h50v50q0 21 14.5 35.5t35.5 14.5zM800 850v150q41 0 70.5 -29.5t29.5 -70.5v-500 h-200v-300h200q0 -36 -7 -57.5t-23.5 -30t-29.5 -10.5t-40 -2h-600q-41 0 -70.5 29.5t-29.5 70.5v800q0 41 29.5 70.5t70.5 29.5v-150q0 -62 44 -106t106 -44h300q62 0 106 44t44 106zM1212 250l-212 -212v162h-200v100h200v162z" /> +<glyph unicode="" d="M658 1197l637 -1104q23 -38 7 -65.5t-60 -27.5h-1276q-44 0 -60 27.5t7 65.5l637 1104q22 39 54 39t54 -39zM704 800h-208q-20 0 -32 -14.5t-8 -34.5l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5zM500 300v-100h200 v100h-200z" /> +<glyph unicode="" d="M425 1100h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM825 800h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM25 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5zM425 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 500h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5 v150q0 10 7.5 17.5t17.5 7.5zM25 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM425 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5 t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM825 200h250q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-250q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M700 1200h100v-200h-100v-100h350q62 0 86.5 -39.5t-3.5 -94.5l-66 -132q-41 -83 -81 -134h-772q-40 51 -81 134l-66 132q-28 55 -3.5 94.5t86.5 39.5h350v100h-100v200h100v100h200v-100zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-12l137 -100 h-950l138 100h-13q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1300q40 0 68.5 -29.5t28.5 -70.5h-194q0 41 28.5 70.5t68.5 29.5zM443 1100h314q18 -37 18 -75q0 -8 -3 -25h328q41 0 44.5 -16.5t-30.5 -38.5l-175 -145h-678l-178 145q-34 22 -29 38.5t46 16.5h328q-3 17 -3 25q0 38 18 75zM250 700h700q21 0 35.5 -14.5 t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-150v-200l275 -200h-950l275 200v200h-150q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1181q75 0 128 -53t53 -128t-53 -128t-128 -53t-128 53t-53 128t53 128t128 53zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13 l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1300q47 0 92.5 -53.5t71 -123t25.5 -123.5q0 -78 -55.5 -133.5t-133.5 -55.5t-133.5 55.5t-55.5 133.5q0 62 34 143l144 -143l111 111l-163 163q34 26 63 26zM602 798h46q34 0 55.5 -28.5t21.5 -86.5q0 -76 39 -183h-324q39 107 39 183q0 58 21.5 86.5t56.5 28.5h45 zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1200l300 -161v-139h-300q0 -57 18.5 -108t50 -91.5t63 -72t70 -67.5t57.5 -61h-530q-60 83 -90.5 177.5t-30.5 178.5t33 164.5t87.5 139.5t126 96.5t145.5 41.5v-98zM250 400h700q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-13l138 -100h-950l137 100 h-12q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5zM50 100h1100q21 0 35.5 -14.5t14.5 -35.5v-50h-1200v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1300q41 0 70.5 -29.5t29.5 -70.5v-78q46 -26 73 -72t27 -100v-50h-400v50q0 54 27 100t73 72v78q0 41 29.5 70.5t70.5 29.5zM400 800h400q54 0 100 -27t72 -73h-172v-100h200v-100h-200v-100h200v-100h-200v-100h200q0 -83 -58.5 -141.5t-141.5 -58.5h-400 q-83 0 -141.5 58.5t-58.5 141.5v400q0 83 58.5 141.5t141.5 58.5z" /> +<glyph unicode="" d="M150 1100h900q21 0 35.5 -14.5t14.5 -35.5v-500q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v500q0 21 14.5 35.5t35.5 14.5zM125 400h950q10 0 17.5 -7.5t7.5 -17.5v-50q0 -10 -7.5 -17.5t-17.5 -7.5h-283l224 -224q13 -13 13 -31.5t-13 -32 t-31.5 -13.5t-31.5 13l-88 88h-524l-87 -88q-13 -13 -32 -13t-32 13.5t-13 32t13 31.5l224 224h-289q-10 0 -17.5 7.5t-7.5 17.5v50q0 10 7.5 17.5t17.5 7.5zM541 300l-100 -100h324l-100 100h-124z" /> +<glyph unicode="" d="M200 1100h800q83 0 141.5 -58.5t58.5 -141.5v-200h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100q0 41 -29.5 70.5t-70.5 29.5h-250q-41 0 -70.5 -29.5t-29.5 -70.5h-100v200q0 83 58.5 141.5t141.5 58.5zM100 600h1000q41 0 70.5 -29.5 t29.5 -70.5v-300h-1200v300q0 41 29.5 70.5t70.5 29.5zM300 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200zM1100 100v-50q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v50h200z" /> +<glyph unicode="" d="M480 1165l682 -683q31 -31 31 -75.5t-31 -75.5l-131 -131h-481l-517 518q-32 31 -32 75.5t32 75.5l295 296q31 31 75.5 31t76.5 -31zM108 794l342 -342l303 304l-341 341zM250 100h800q21 0 35.5 -14.5t14.5 -35.5v-50h-900v50q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M1057 647l-189 506q-8 19 -27.5 33t-40.5 14h-400q-21 0 -40.5 -14t-27.5 -33l-189 -506q-8 -19 1.5 -33t30.5 -14h625v-150q0 -21 14.5 -35.5t35.5 -14.5t35.5 14.5t14.5 35.5v150h125q21 0 30.5 14t1.5 33zM897 0h-595v50q0 21 14.5 35.5t35.5 14.5h50v50 q0 21 14.5 35.5t35.5 14.5h48v300h200v-300h47q21 0 35.5 -14.5t14.5 -35.5v-50h50q21 0 35.5 -14.5t14.5 -35.5v-50z" /> +<glyph unicode="" d="M900 800h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-375v591l-300 300v84q0 10 7.5 17.5t17.5 7.5h375v-400zM1200 900h-200v200zM400 600h300v-575q0 -10 -7.5 -17.5t-17.5 -7.5h-650q-10 0 -17.5 7.5t-7.5 17.5v950q0 10 7.5 17.5t17.5 7.5h375v-400zM700 700h-200v200z " /> +<glyph unicode="" d="M484 1095h195q75 0 146 -32.5t124 -86t89.5 -122.5t48.5 -142q18 -14 35 -20q31 -10 64.5 6.5t43.5 48.5q10 34 -15 71q-19 27 -9 43q5 8 12.5 11t19 -1t23.5 -16q41 -44 39 -105q-3 -63 -46 -106.5t-104 -43.5h-62q-7 -55 -35 -117t-56 -100l-39 -234q-3 -20 -20 -34.5 t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l12 70q-49 -14 -91 -14h-195q-24 0 -65 8l-11 -64q-3 -20 -20 -34.5t-38 -14.5h-100q-21 0 -33 14.5t-9 34.5l26 157q-84 74 -128 175l-159 53q-19 7 -33 26t-14 40v50q0 21 14.5 35.5t35.5 14.5h124q11 87 56 166l-111 95 q-16 14 -12.5 23.5t24.5 9.5h203q116 101 250 101zM675 1000h-250q-10 0 -17.5 -7.5t-7.5 -17.5v-50q0 -10 7.5 -17.5t17.5 -7.5h250q10 0 17.5 7.5t7.5 17.5v50q0 10 -7.5 17.5t-17.5 7.5z" /> +<glyph unicode="" d="M641 900l423 247q19 8 42 2.5t37 -21.5l32 -38q14 -15 12.5 -36t-17.5 -34l-139 -120h-390zM50 1100h106q67 0 103 -17t66 -71l102 -212h823q21 0 35.5 -14.5t14.5 -35.5v-50q0 -21 -14 -40t-33 -26l-737 -132q-23 -4 -40 6t-26 25q-42 67 -100 67h-300q-62 0 -106 44 t-44 106v200q0 62 44 106t106 44zM173 928h-80q-19 0 -28 -14t-9 -35v-56q0 -51 42 -51h134q16 0 21.5 8t5.5 24q0 11 -16 45t-27 51q-18 28 -43 28zM550 727q-32 0 -54.5 -22.5t-22.5 -54.5t22.5 -54.5t54.5 -22.5t54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5zM130 389 l152 130q18 19 34 24t31 -3.5t24.5 -17.5t25.5 -28q28 -35 50.5 -51t48.5 -13l63 5l48 -179q13 -61 -3.5 -97.5t-67.5 -79.5l-80 -69q-47 -40 -109 -35.5t-103 51.5l-130 151q-40 47 -35.5 109.5t51.5 102.5zM380 377l-102 -88q-31 -27 2 -65l37 -43q13 -15 27.5 -19.5 t31.5 6.5l61 53q19 16 14 49q-2 20 -12 56t-17 45q-11 12 -19 14t-23 -8z" /> +<glyph unicode="" d="M625 1200h150q10 0 17.5 -7.5t7.5 -17.5v-109q79 -33 131 -87.5t53 -128.5q1 -46 -15 -84.5t-39 -61t-46 -38t-39 -21.5l-17 -6q6 0 15 -1.5t35 -9t50 -17.5t53 -30t50 -45t35.5 -64t14.5 -84q0 -59 -11.5 -105.5t-28.5 -76.5t-44 -51t-49.5 -31.5t-54.5 -16t-49.5 -6.5 t-43.5 -1v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-100v-75q0 -10 -7.5 -17.5t-17.5 -7.5h-150q-10 0 -17.5 7.5t-7.5 17.5v75h-175q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5h75v600h-75q-10 0 -17.5 7.5t-7.5 17.5v150 q0 10 7.5 17.5t17.5 7.5h175v75q0 10 7.5 17.5t17.5 7.5h150q10 0 17.5 -7.5t7.5 -17.5v-75h100v75q0 10 7.5 17.5t17.5 7.5zM400 900v-200h263q28 0 48.5 10.5t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-263zM400 500v-200h363q28 0 48.5 10.5 t30 25t15 29t5.5 25.5l1 10q0 4 -0.5 11t-6 24t-15 30t-30 24t-48.5 11h-363z" /> +<glyph unicode="" d="M212 1198h780q86 0 147 -61t61 -147v-416q0 -51 -18 -142.5t-36 -157.5l-18 -66q-29 -87 -93.5 -146.5t-146.5 -59.5h-572q-82 0 -147 59t-93 147q-8 28 -20 73t-32 143.5t-20 149.5v416q0 86 61 147t147 61zM600 1045q-70 0 -132.5 -11.5t-105.5 -30.5t-78.5 -41.5 t-57 -45t-36 -41t-20.5 -30.5l-6 -12l156 -243h560l156 243q-2 5 -6 12.5t-20 29.5t-36.5 42t-57 44.5t-79 42t-105 29.5t-132.5 12zM762 703h-157l195 261z" /> +<glyph unicode="" d="M475 1300h150q103 0 189 -86t86 -189v-500q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" /> +<glyph unicode="" d="M475 1300h96q0 -150 89.5 -239.5t239.5 -89.5v-446q0 -41 -42 -83t-83 -42h-450q-41 0 -83 42t-42 83v500q0 103 86 189t189 86zM700 300v-225q0 -21 -27 -48t-48 -27h-150q-21 0 -48 27t-27 48v225h300z" /> +<glyph unicode="" d="M1294 767l-638 -283l-378 170l-78 -60v-224l100 -150v-199l-150 148l-150 -149v200l100 150v250q0 4 -0.5 10.5t0 9.5t1 8t3 8t6.5 6l47 40l-147 65l642 283zM1000 380l-350 -166l-350 166v147l350 -165l350 165v-147z" /> +<glyph unicode="" d="M250 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM650 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM1050 800q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" /> +<glyph unicode="" d="M550 1100q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 700q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44zM550 300q62 0 106 -44t44 -106t-44 -106t-106 -44t-106 44t-44 106t44 106t106 44z" /> +<glyph unicode="" d="M125 1100h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5zM125 700h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5 t17.5 7.5zM125 300h950q10 0 17.5 -7.5t7.5 -17.5v-150q0 -10 -7.5 -17.5t-17.5 -7.5h-950q-10 0 -17.5 7.5t-7.5 17.5v150q0 10 7.5 17.5t17.5 7.5z" /> +<glyph unicode="" d="M350 1200h500q162 0 256 -93.5t94 -256.5v-500q0 -165 -93.5 -257.5t-256.5 -92.5h-500q-165 0 -257.5 92.5t-92.5 257.5v500q0 165 92.5 257.5t257.5 92.5zM900 1000h-600q-41 0 -70.5 -29.5t-29.5 -70.5v-600q0 -41 29.5 -70.5t70.5 -29.5h600q41 0 70.5 29.5 t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5zM350 900h500q21 0 35.5 -14.5t14.5 -35.5v-300q0 -21 -14.5 -35.5t-35.5 -14.5h-500q-21 0 -35.5 14.5t-14.5 35.5v300q0 21 14.5 35.5t35.5 14.5zM400 800v-200h400v200h-400z" /> +<glyph unicode="" d="M150 1100h1000q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5t-35.5 -14.5h-50v-200h50q21 0 35.5 -14.5t14.5 -35.5t-14.5 -35.5 t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5h50v200h-50q-21 0 -35.5 14.5t-14.5 35.5t14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M650 1187q87 -67 118.5 -156t0 -178t-118.5 -155q-87 66 -118.5 155t0 178t118.5 156zM300 800q124 0 212 -88t88 -212q-124 0 -212 88t-88 212zM1000 800q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM300 500q124 0 212 -88t88 -212q-124 0 -212 88t-88 212z M1000 500q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM700 199v-144q0 -21 -14.5 -35.5t-35.5 -14.5t-35.5 14.5t-14.5 35.5v142q40 -4 43 -4q17 0 57 6z" /> +<glyph unicode="" d="M745 878l69 19q25 6 45 -12l298 -295q11 -11 15 -26.5t-2 -30.5q-5 -14 -18 -23.5t-28 -9.5h-8q1 0 1 -13q0 -29 -2 -56t-8.5 -62t-20 -63t-33 -53t-51 -39t-72.5 -14h-146q-184 0 -184 288q0 24 10 47q-20 4 -62 4t-63 -4q11 -24 11 -47q0 -288 -184 -288h-142 q-48 0 -84.5 21t-56 51t-32 71.5t-16 75t-3.5 68.5q0 13 2 13h-7q-15 0 -27.5 9.5t-18.5 23.5q-6 15 -2 30.5t15 25.5l298 296q20 18 46 11l76 -19q20 -5 30.5 -22.5t5.5 -37.5t-22.5 -31t-37.5 -5l-51 12l-182 -193h891l-182 193l-44 -12q-20 -5 -37.5 6t-22.5 31t6 37.5 t31 22.5z" /> +<glyph unicode="" d="M1200 900h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-200v-850q0 -22 25 -34.5t50 -13.5l25 -2v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v850h-200q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h1000v-300zM500 450h-25q0 15 -4 24.5t-9 14.5t-17 7.5t-20 3t-25 0.5h-100v-425q0 -11 12.5 -17.5t25.5 -7.5h12v-50h-200v50q50 0 50 25v425h-100q-17 0 -25 -0.5t-20 -3t-17 -7.5t-9 -14.5t-4 -24.5h-25v150h500v-150z" /> +<glyph unicode="" d="M1000 300v50q-25 0 -55 32q-14 14 -25 31t-16 27l-4 11l-289 747h-69l-300 -754q-18 -35 -39 -56q-9 -9 -24.5 -18.5t-26.5 -14.5l-11 -5v-50h273v50q-49 0 -78.5 21.5t-11.5 67.5l69 176h293l61 -166q13 -34 -3.5 -66.5t-55.5 -32.5v-50h312zM412 691l134 342l121 -342 h-255zM1100 150v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5z" /> +<glyph unicode="" d="M50 1200h1100q21 0 35.5 -14.5t14.5 -35.5v-1100q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-21 0 -35.5 14.5t-14.5 35.5v1100q0 21 14.5 35.5t35.5 14.5zM611 1118h-70q-13 0 -18 -12l-299 -753q-17 -32 -35 -51q-18 -18 -56 -34q-12 -5 -12 -18v-50q0 -8 5.5 -14t14.5 -6 h273q8 0 14 6t6 14v50q0 8 -6 14t-14 6q-55 0 -71 23q-10 14 0 39l63 163h266l57 -153q11 -31 -6 -55q-12 -17 -36 -17q-8 0 -14 -6t-6 -14v-50q0 -8 6 -14t14 -6h313q8 0 14 6t6 14v50q0 7 -5.5 13t-13.5 7q-17 0 -42 25q-25 27 -40 63h-1l-288 748q-5 12 -19 12zM639 611 h-197l103 264z" /> +<glyph unicode="" d="M1200 1100h-1200v100h1200v-100zM50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 1000h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM700 900v-300h300v300h-300z" /> +<glyph unicode="" d="M50 1200h400q21 0 35.5 -14.5t14.5 -35.5v-900q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v900q0 21 14.5 35.5t35.5 14.5zM650 700h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400 q0 21 14.5 35.5t35.5 14.5zM700 600v-300h300v300h-300zM1200 0h-1200v100h1200v-100z" /> +<glyph unicode="" d="M50 1000h400q21 0 35.5 -14.5t14.5 -35.5v-350h100v150q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-150h100v-100h-100v-150q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v150h-100v-350q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5v800q0 21 14.5 35.5t35.5 14.5zM700 700v-300h300v300h-300z" /> +<glyph unicode="" d="M100 0h-100v1200h100v-1200zM250 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM300 1000v-300h300v300h-300zM250 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M600 1100h150q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-100h450q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h350v100h-150q-21 0 -35.5 14.5 t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5h150v100h100v-100zM400 1000v-300h300v300h-300z" /> +<glyph unicode="" d="M1200 0h-100v1200h100v-1200zM550 1100h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM600 1000v-300h300v300h-300zM50 500h900q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-900q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5z" /> +<glyph unicode="" d="M865 565l-494 -494q-23 -23 -41 -23q-14 0 -22 13.5t-8 38.5v1000q0 25 8 38.5t22 13.5q18 0 41 -23l494 -494q14 -14 14 -35t-14 -35z" /> +<glyph unicode="" d="M335 635l494 494q29 29 50 20.5t21 -49.5v-1000q0 -41 -21 -49.5t-50 20.5l-494 494q-14 14 -14 35t14 35z" /> +<glyph unicode="" d="M100 900h1000q41 0 49.5 -21t-20.5 -50l-494 -494q-14 -14 -35 -14t-35 14l-494 494q-29 29 -20.5 50t49.5 21z" /> +<glyph unicode="" d="M635 865l494 -494q29 -29 20.5 -50t-49.5 -21h-1000q-41 0 -49.5 21t20.5 50l494 494q14 14 35 14t35 -14z" /> +<glyph unicode="" d="M700 741v-182l-692 -323v221l413 193l-413 193v221zM1200 0h-800v200h800v-200z" /> +<glyph unicode="" d="M1200 900h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300zM0 700h50q0 21 4 37t9.5 26.5t18 17.5t22 11t28.5 5.5t31 2t37 0.5h100v-550q0 -22 -25 -34.5t-50 -13.5l-25 -2v-100h400v100q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v550h100q25 0 37 -0.5t31 -2 t28.5 -5.5t22 -11t18 -17.5t9.5 -26.5t4 -37h50v300h-800v-300z" /> +<glyph unicode="" d="M800 700h-50q0 21 -4 37t-9.5 26.5t-18 17.5t-22 11t-28.5 5.5t-31 2t-37 0.5h-100v-550q0 -22 25 -34.5t50 -14.5l25 -1v-100h-400v100q4 0 11 0.5t24 3t30 7t24 15t11 24.5v550h-100q-25 0 -37 -0.5t-31 -2t-28.5 -5.5t-22 -11t-18 -17.5t-9.5 -26.5t-4 -37h-50v300 h800v-300zM1100 200h-200v-100h200v-100h-300v300h200v100h-200v100h300v-300z" /> +<glyph unicode="" d="M701 1098h160q16 0 21 -11t-7 -23l-464 -464l464 -464q12 -12 7 -23t-21 -11h-160q-13 0 -23 9l-471 471q-7 8 -7 18t7 18l471 471q10 9 23 9z" /> +<glyph unicode="" d="M339 1098h160q13 0 23 -9l471 -471q7 -8 7 -18t-7 -18l-471 -471q-10 -9 -23 -9h-160q-16 0 -21 11t7 23l464 464l-464 464q-12 12 -7 23t21 11z" /> +<glyph unicode="" d="M1087 882q11 -5 11 -21v-160q0 -13 -9 -23l-471 -471q-8 -7 -18 -7t-18 7l-471 471q-9 10 -9 23v160q0 16 11 21t23 -7l464 -464l464 464q12 12 23 7z" /> +<glyph unicode="" d="M618 993l471 -471q9 -10 9 -23v-160q0 -16 -11 -21t-23 7l-464 464l-464 -464q-12 -12 -23 -7t-11 21v160q0 13 9 23l471 471q8 7 18 7t18 -7z" /> +<glyph unicode="" d="M1000 1200q0 -124 -88 -212t-212 -88q0 124 88 212t212 88zM450 1000h100q21 0 40 -14t26 -33l79 -194q5 1 16 3q34 6 54 9.5t60 7t65.5 1t61 -10t56.5 -23t42.5 -42t29 -64t5 -92t-19.5 -121.5q-1 -7 -3 -19.5t-11 -50t-20.5 -73t-32.5 -81.5t-46.5 -83t-64 -70 t-82.5 -50q-13 -5 -42 -5t-65.5 2.5t-47.5 2.5q-14 0 -49.5 -3.5t-63 -3.5t-43.5 7q-57 25 -104.5 78.5t-75 111.5t-46.5 112t-26 90l-7 35q-15 63 -18 115t4.5 88.5t26 64t39.5 43.5t52 25.5t58.5 13t62.5 2t59.5 -4.5t55.5 -8l-147 192q-12 18 -5.5 30t27.5 12z" /> +<glyph unicode="🔑" d="M250 1200h600q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-150v-500l-255 -178q-19 -9 -32 -1t-13 29v650h-150q-21 0 -35.5 14.5t-14.5 35.5v400q0 21 14.5 35.5t35.5 14.5zM400 1100v-100h300v100h-300z" /> +<glyph unicode="🚪" d="M250 1200h750q39 0 69.5 -40.5t30.5 -84.5v-933l-700 -117v950l600 125h-700v-1000h-100v1025q0 23 15.5 49t34.5 26zM500 525v-100l100 20v100z" /> </font> </defs></svg>
\ No newline at end of file diff --git a/bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf b/bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf Binary files differindex 67fa00b..1413fc6 100644 --- a/bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf +++ b/bower_components/bootstrap/fonts/glyphicons-halflings-regular.ttf diff --git a/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff b/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff Binary files differindex 8c54182..9e61285 100644 --- a/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff +++ b/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff diff --git a/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff2 b/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff2 Binary files differnew file mode 100644 index 0000000..64539b5 --- /dev/null +++ b/bower_components/bootstrap/fonts/glyphicons-halflings-regular.woff2 diff --git a/bower_components/bootstrap/grunt/.jshintrc b/bower_components/bootstrap/grunt/.jshintrc new file mode 100644 index 0000000..0ea0495 --- /dev/null +++ b/bower_components/bootstrap/grunt/.jshintrc @@ -0,0 +1,7 @@ +{ + "extends" : "../js/.jshintrc", + "asi" : false, + "browser" : false, + "es3" : false, + "node" : true +} diff --git a/bower_components/bootstrap/grunt/bs-commonjs-generator.js b/bower_components/bootstrap/grunt/bs-commonjs-generator.js new file mode 100644 index 0000000..0b4ebbf --- /dev/null +++ b/bower_components/bootstrap/grunt/bs-commonjs-generator.js @@ -0,0 +1,30 @@ +/*! + * Bootstrap Grunt task for the CommonJS module generation + * http://getbootstrap.com + * Copyright 2014-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +'use strict'; + +var fs = require('fs'); +var path = require('path'); + +var COMMONJS_BANNER = '// This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.\n'; + +module.exports = function generateCommonJSModule(grunt, srcFiles, destFilepath) { + var destDir = path.dirname(destFilepath); + + function srcPathToDestRequire(srcFilepath) { + var requirePath = path.relative(destDir, srcFilepath).replace(/\\/g, '/'); + return 'require(\'' + requirePath + '\')'; + } + + var moduleOutputJs = COMMONJS_BANNER + srcFiles.map(srcPathToDestRequire).join('\n'); + try { + fs.writeFileSync(destFilepath, moduleOutputJs); + } catch (err) { + grunt.fail.warn(err); + } + grunt.log.writeln('File ' + destFilepath.cyan + ' created.'); +}; diff --git a/bower_components/bootstrap/grunt/bs-glyphicons-data-generator.js b/bower_components/bootstrap/grunt/bs-glyphicons-data-generator.js index 82dc727..af2a82e 100644 --- a/bower_components/bootstrap/grunt/bs-glyphicons-data-generator.js +++ b/bower_components/bootstrap/grunt/bs-glyphicons-data-generator.js @@ -1,10 +1,12 @@ /*! * Bootstrap Grunt task for Glyphicons data generation * http://getbootstrap.com - * Copyright 2014 Twitter, Inc. + * Copyright 2014-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ + 'use strict'; + var fs = require('fs'); module.exports = function generateGlyphiconsData(grunt) { @@ -14,7 +16,7 @@ module.exports = function generateGlyphiconsData(grunt) { var glyphiconsLines = glyphiconsFile.split('\n'); // Use any line that starts with ".glyphicon-" and capture the class name - var iconClassName = /^\.(glyphicon-[^\s]+)/; + var iconClassName = /^\.(glyphicon-[a-zA-Z0-9-]+)/; var glyphiconsData = '# This file is generated via Grunt task. **Do not edit directly.**\n' + '# See the \'build-glyphicons-data\' task in Gruntfile.js.\n\n'; var glyphiconsYml = 'docs/_data/glyphicons.yml'; @@ -33,8 +35,7 @@ module.exports = function generateGlyphiconsData(grunt) { try { fs.writeFileSync(glyphiconsYml, glyphiconsData); - } - catch (err) { + } catch (err) { grunt.fail.warn(err); } grunt.log.writeln('File ' + glyphiconsYml.cyan + ' created.'); diff --git a/bower_components/bootstrap/grunt/bs-lessdoc-parser.js b/bower_components/bootstrap/grunt/bs-lessdoc-parser.js index c1821de..5a9ed2b 100644 --- a/bower_components/bootstrap/grunt/bs-lessdoc-parser.js +++ b/bower_components/bootstrap/grunt/bs-lessdoc-parser.js @@ -1,16 +1,19 @@ /*! * Bootstrap Grunt task for parsing Less docstrings * http://getbootstrap.com - * Copyright 2014 Twitter, Inc. + * Copyright 2014-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ + 'use strict'; -var markdown = require('markdown').markdown; +var Markdown = require('markdown-it'); function markdown2html(markdownString) { + var md = new Markdown(); + // the slice removes the <p>...</p> wrapper output by Markdown processor - return markdown.toHTML(markdownString.trim()).slice(3, -4); + return md.render(markdownString.trim()).slice(3, -5); } @@ -33,9 +36,9 @@ Mini-language: var CUSTOMIZABLE_HEADING = /^[/]{2}={2}(.*)$/; var UNCUSTOMIZABLE_HEADING = /^[/]{2}-{2}(.*)$/; var SUBSECTION_HEADING = /^[/]{2}={3}(.*)$/; -var SECTION_DOCSTRING = /^[/]{2}#{2}(.*)$/; -var VAR_ASSIGNMENT = /^(@[a-zA-Z0-9_-]+):[ ]*([^ ;][^;]+);[ ]*$/; -var VAR_DOCSTRING = /^[/]{2}[*]{2}(.*)$/; +var SECTION_DOCSTRING = /^[/]{2}#{2}(.+)$/; +var VAR_ASSIGNMENT = /^(@[a-zA-Z0-9_-]+):[ ]*([^ ;][^;]*);[ ]*$/; +var VAR_DOCSTRING = /^[/]{2}[*]{2}(.+)$/; function Section(heading, customizable) { this.heading = heading.trim(); @@ -119,7 +122,7 @@ Tokenizer.prototype._shift = function () { return new VarDocstring(match[1]); } var commentStart = line.lastIndexOf('//'); - var varLine = (commentStart === -1) ? line : line.slice(0, commentStart); + var varLine = commentStart === -1 ? line : line.slice(0, commentStart); match = VAR_ASSIGNMENT.exec(varLine); if (match !== null) { return new Variable(match[1], match[2]); @@ -166,8 +169,7 @@ Parser.prototype.parseSection = function () { var docstring = this._tokenizer.shift(); if (docstring instanceof SectionDocstring) { section.docstring = docstring; - } - else { + } else { this._tokenizer.unshift(docstring); } this.parseSubSections(section); @@ -183,15 +185,14 @@ Parser.prototype.parseSubSections = function (section) { // Presume an implicit initial subsection subsection = new SubSection(''); this.parseVars(subsection); - } - else { + } else { break; } } section.addSubSection(subsection); } - if (section.subsections.length === 1 && !(section.subsections[0].heading) && section.subsections[0].variables.length === 0) { + if (section.subsections.length === 1 && !section.subsections[0].heading && section.subsections[0].variables.length === 0) { // Ignore lone empty implicit subsection section.subsections = []; } diff --git a/bower_components/bootstrap/grunt/bs-raw-files-generator.js b/bower_components/bootstrap/grunt/bs-raw-files-generator.js index ec8c531..39224e4 100644 --- a/bower_components/bootstrap/grunt/bs-raw-files-generator.js +++ b/bower_components/bootstrap/grunt/bs-raw-files-generator.js @@ -1,28 +1,27 @@ /*! * Bootstrap Grunt task for generating raw-files.min.js for the Customizer * http://getbootstrap.com - * Copyright 2014 Twitter, Inc. + * Copyright 2014-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ -/* global btoa: true */ - 'use strict'; + var fs = require('fs'); var btoa = require('btoa'); var glob = require('glob'); function getFiles(type) { var files = {}; - var recursive = (type === 'less'); - var globExpr = (recursive ? '/**/*' : '/*'); + var recursive = type === 'less'; + var globExpr = recursive ? '/**/*' : '/*'; glob.sync(type + globExpr) .filter(function (path) { return type === 'fonts' ? true : new RegExp('\\.' + type + '$').test(path); }) .forEach(function (fullPath) { var relativePath = fullPath.replace(/^[^/]+\//, ''); - files[relativePath] = (type === 'fonts' ? btoa(fs.readFileSync(fullPath)) : fs.readFileSync(fullPath, 'utf8')); + files[relativePath] = type === 'fonts' ? btoa(fs.readFileSync(fullPath)) : fs.readFileSync(fullPath, 'utf8'); }); return 'var __' + type + ' = ' + JSON.stringify(files) + '\n'; } @@ -38,8 +37,7 @@ module.exports = function generateRawFilesJs(grunt, banner) { var rawFilesJs = 'docs/assets/js/raw-files.min.js'; try { fs.writeFileSync(rawFilesJs, files); - } - catch (err) { + } catch (err) { grunt.fail.warn(err); } grunt.log.writeln('File ' + rawFilesJs.cyan + ' created.'); diff --git a/bower_components/bootstrap/grunt/configBridge.json b/bower_components/bootstrap/grunt/configBridge.json new file mode 100644 index 0000000..8ce4c3d --- /dev/null +++ b/bower_components/bootstrap/grunt/configBridge.json @@ -0,0 +1,46 @@ +{ + "paths": { + "customizerJs": [ + "../assets/js/vendor/autoprefixer.js", + "../assets/js/vendor/less.min.js", + "../assets/js/vendor/jszip.min.js", + "../assets/js/vendor/uglify.min.js", + "../assets/js/vendor/Blob.js", + "../assets/js/vendor/FileSaver.js", + "../assets/js/raw-files.min.js", + "../assets/js/src/customizer.js" + ], + "docsJs": [ + "../assets/js/vendor/holder.min.js", + "../assets/js/vendor/ZeroClipboard.min.js", + "../assets/js/vendor/anchor.js", + "../assets/js/src/application.js" + ] + }, + "config": { + "autoprefixerBrowsers": [ + "Android 2.3", + "Android >= 4", + "Chrome >= 20", + "Firefox >= 24", + "Explorer >= 8", + "iOS >= 6", + "Opera >= 12", + "Safari >= 6" + ], + "jqueryCheck": [ + "if (typeof jQuery === 'undefined') {", + " throw new Error('Bootstrap\\'s JavaScript requires jQuery')", + "}\n" + ], + "jqueryVersionCheck": [ + "+function ($) {", + " 'use strict';", + " var version = $.fn.jquery.split(' ')[0].split('.')", + " if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1)) {", + " throw new Error('Bootstrap\\'s JavaScript requires jQuery version 1.9.1 or higher')", + " }", + "}(jQuery);\n\n" + ] + } +}
\ No newline at end of file diff --git a/bower_components/bootstrap/grunt/sauce_browsers.yml b/bower_components/bootstrap/grunt/sauce_browsers.yml index 8014bfc..6267f35 100644 --- a/bower_components/bootstrap/grunt/sauce_browsers.yml +++ b/bower_components/bootstrap/grunt/sauce_browsers.yml @@ -3,15 +3,15 @@ { browserName: "safari", - platform: "OS X 10.9" + platform: "OS X 10.10" }, { browserName: "chrome", - platform: "OS X 10.9" + platform: "OS X 10.10" }, { browserName: "firefox", - platform: "OS X 10.9" + platform: "OS X 10.10" }, # Mac Opera not currently supported by Sauce Labs @@ -56,8 +56,8 @@ { browserName: "iphone", - platform: "OS X 10.9", - version: "7.1" + platform: "OS X 10.10", + version: "8.2" }, # iOS Chrome not currently supported by Sauce Labs diff --git a/bower_components/bootstrap/js/.jscsrc b/bower_components/bootstrap/js/.jscsrc new file mode 100644 index 0000000..9544d2d --- /dev/null +++ b/bower_components/bootstrap/js/.jscsrc @@ -0,0 +1,42 @@ +{ + "disallowEmptyBlocks": true, + "disallowKeywords": ["with"], + "disallowMixedSpacesAndTabs": true, + "disallowMultipleLineStrings": true, + "disallowMultipleVarDecl": true, + "disallowQuotedKeysInObjects": "allButReserved", + "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], + "disallowSpaceBeforeBinaryOperators": [","], + "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], + "disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true }, + "disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true }, + "disallowSpacesInsideArrayBrackets": true, + "disallowSpacesInsideParentheses": true, + "disallowTrailingComma": true, + "disallowTrailingWhitespace": true, + "requireCamelCaseOrUpperCaseIdentifiers": true, + "requireCapitalizedConstructors": true, + "requireCommaBeforeLineBreak": true, + "requireDollarBeforejQueryAssignment": true, + "requireDotNotation": true, + "requireLineFeedAtFileEnd": true, + "requirePaddingNewLinesAfterUseStrict": true, + "requirePaddingNewLinesBeforeExport": true, + "requireSpaceAfterBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="], + "requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"], + "requireSpaceAfterLineComment": true, + "requireSpaceBeforeBinaryOperators": ["+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", "<", ">=", "<="], + "requireSpaceBetweenArguments": true, + "requireSpacesInAnonymousFunctionExpression": { "beforeOpeningCurlyBrace": true, "beforeOpeningRoundBrace": true }, + "requireSpacesInConditionalExpression": true, + "requireSpacesInForStatement": true, + "requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true }, + "requireSpacesInFunctionExpression": { "beforeOpeningCurlyBrace": true }, + "requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true }, + "requireSpacesInsideObjectBrackets": "allButNested", + "validateAlignedFunctionParameters": true, + "validateIndentation": 2, + "validateLineBreaks": "LF", + "validateNewlineAfterArrayElements": true, + "validateQuoteMarks": "'" +} diff --git a/bower_components/bootstrap/js/.jshintrc b/bower_components/bootstrap/js/.jshintrc new file mode 100644 index 0000000..a59e1d0 --- /dev/null +++ b/bower_components/bootstrap/js/.jshintrc @@ -0,0 +1,15 @@ +{ + "asi" : true, + "browser" : true, + "eqeqeq" : false, + "eqnull" : true, + "es3" : true, + "expr" : true, + "jquery" : true, + "latedef" : true, + "laxbreak" : true, + "nonbsp" : true, + "strict" : true, + "undef" : true, + "unused" : true +} diff --git a/bower_components/bootstrap/js/affix.js b/bower_components/bootstrap/js/affix.js index 7d404eb..11a3d39 100644 --- a/bower_components/bootstrap/js/affix.js +++ b/bower_components/bootstrap/js/affix.js @@ -1,8 +1,8 @@ /* ======================================================================== - * Bootstrap: affix.js v3.2.0 + * Bootstrap: affix.js v3.3.5 * http://getbootstrap.com/javascript/#affix * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. + * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ @@ -21,14 +21,14 @@ .on('click.bs.affix.data-api', $.proxy(this.checkPositionWithEventLoop, this)) this.$element = $(element) - this.affixed = - this.unpin = + this.affixed = null + this.unpin = null this.pinnedOffset = null this.checkPosition() } - Affix.VERSION = '3.2.0' + Affix.VERSION = '3.3.5' Affix.RESET = 'affix affix-top affix-bottom' @@ -37,6 +37,28 @@ target: window } + Affix.prototype.getState = function (scrollHeight, height, offsetTop, offsetBottom) { + var scrollTop = this.$target.scrollTop() + var position = this.$element.offset() + var targetHeight = this.$target.height() + + if (offsetTop != null && this.affixed == 'top') return scrollTop < offsetTop ? 'top' : false + + if (this.affixed == 'bottom') { + if (offsetTop != null) return (scrollTop + this.unpin <= position.top) ? false : 'bottom' + return (scrollTop + targetHeight <= scrollHeight - offsetBottom) ? false : 'bottom' + } + + var initializing = this.affixed == null + var colliderTop = initializing ? scrollTop : position.top + var colliderHeight = initializing ? targetHeight : height + + if (offsetTop != null && scrollTop <= offsetTop) return 'top' + if (offsetBottom != null && (colliderTop + colliderHeight >= scrollHeight - offsetBottom)) return 'bottom' + + return false + } + Affix.prototype.getPinnedOffset = function () { if (this.pinnedOffset) return this.pinnedOffset this.$element.removeClass(Affix.RESET).addClass('affix') @@ -52,42 +74,40 @@ Affix.prototype.checkPosition = function () { if (!this.$element.is(':visible')) return - var scrollHeight = $(document).height() - var scrollTop = this.$target.scrollTop() - var position = this.$element.offset() + var height = this.$element.height() var offset = this.options.offset var offsetTop = offset.top var offsetBottom = offset.bottom + var scrollHeight = Math.max($(document).height(), $(document.body).height()) if (typeof offset != 'object') offsetBottom = offsetTop = offset if (typeof offsetTop == 'function') offsetTop = offset.top(this.$element) if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element) - var affix = this.unpin != null && (scrollTop + this.unpin <= position.top) ? false : - offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' : - offsetTop != null && (scrollTop <= offsetTop) ? 'top' : false + var affix = this.getState(scrollHeight, height, offsetTop, offsetBottom) - if (this.affixed === affix) return - if (this.unpin != null) this.$element.css('top', '') + if (this.affixed != affix) { + if (this.unpin != null) this.$element.css('top', '') - var affixType = 'affix' + (affix ? '-' + affix : '') - var e = $.Event(affixType + '.bs.affix') + var affixType = 'affix' + (affix ? '-' + affix : '') + var e = $.Event(affixType + '.bs.affix') - this.$element.trigger(e) + this.$element.trigger(e) - if (e.isDefaultPrevented()) return + if (e.isDefaultPrevented()) return - this.affixed = affix - this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null + this.affixed = affix + this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null - this.$element - .removeClass(Affix.RESET) - .addClass(affixType) - .trigger($.Event(affixType.replace('affix', 'affixed'))) + this.$element + .removeClass(Affix.RESET) + .addClass(affixType) + .trigger(affixType.replace('affix', 'affixed') + '.bs.affix') + } if (affix == 'bottom') { this.$element.offset({ - top: scrollHeight - this.$element.height() - offsetBottom + top: scrollHeight - height - offsetBottom }) } } @@ -132,8 +152,8 @@ data.offset = data.offset || {} - if (data.offsetBottom) data.offset.bottom = data.offsetBottom - if (data.offsetTop) data.offset.top = data.offsetTop + if (data.offsetBottom != null) data.offset.bottom = data.offsetBottom + if (data.offsetTop != null) data.offset.top = data.offsetTop Plugin.call($spy, data) }) diff --git a/bower_components/bootstrap/js/alert.js b/bower_components/bootstrap/js/alert.js index 0efd92c..a7787cb 100644 --- a/bower_components/bootstrap/js/alert.js +++ b/bower_components/bootstrap/js/alert.js @@ -1,8 +1,8 @@ /* ======================================================================== - * Bootstrap: alert.js v3.2.0 + * Bootstrap: alert.js v3.3.5 * http://getbootstrap.com/javascript/#alerts * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. + * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ @@ -18,7 +18,9 @@ $(el).on('click', dismiss, this.close) } - Alert.VERSION = '3.2.0' + Alert.VERSION = '3.3.5' + + Alert.TRANSITION_DURATION = 150 Alert.prototype.close = function (e) { var $this = $(this) @@ -34,7 +36,7 @@ if (e) e.preventDefault() if (!$parent.length) { - $parent = $this.hasClass('alert') ? $this : $this.parent() + $parent = $this.closest('.alert') } $parent.trigger(e = $.Event('close.bs.alert')) @@ -51,7 +53,7 @@ $.support.transition && $parent.hasClass('fade') ? $parent .one('bsTransitionEnd', removeElement) - .emulateTransitionEnd(150) : + .emulateTransitionEnd(Alert.TRANSITION_DURATION) : removeElement() } diff --git a/bower_components/bootstrap/js/button.js b/bower_components/bootstrap/js/button.js index dc3164f..15d7dca 100644 --- a/bower_components/bootstrap/js/button.js +++ b/bower_components/bootstrap/js/button.js @@ -1,8 +1,8 @@ /* ======================================================================== - * Bootstrap: button.js v3.2.0 + * Bootstrap: button.js v3.3.5 * http://getbootstrap.com/javascript/#buttons * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. + * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ @@ -19,7 +19,7 @@ this.isLoading = false } - Button.VERSION = '3.2.0' + Button.VERSION = '3.3.5' Button.DEFAULTS = { loadingText: 'loading...' @@ -31,14 +31,14 @@ var val = $el.is('input') ? 'val' : 'html' var data = $el.data() - state = state + 'Text' + state += 'Text' if (data.resetText == null) $el.data('resetText', $el[val]()) - $el[val](data[state] == null ? this.options[state] : data[state]) - // push to event loop to allow forms to submit setTimeout($.proxy(function () { + $el[val](data[state] == null ? this.options[state] : data[state]) + if (state == 'loadingText') { this.isLoading = true $el.addClass(d).attr(d, d) @@ -56,13 +56,19 @@ if ($parent.length) { var $input = this.$element.find('input') if ($input.prop('type') == 'radio') { - if ($input.prop('checked') && this.$element.hasClass('active')) changed = false - else $parent.find('.active').removeClass('active') + if ($input.prop('checked')) changed = false + $parent.find('.active').removeClass('active') + this.$element.addClass('active') + } else if ($input.prop('type') == 'checkbox') { + if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false + this.$element.toggleClass('active') } - if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') + $input.prop('checked', this.$element.hasClass('active')) + if (changed) $input.trigger('change') + } else { + this.$element.attr('aria-pressed', !this.$element.hasClass('active')) + this.$element.toggleClass('active') } - - if (changed) this.$element.toggleClass('active') } @@ -100,11 +106,15 @@ // BUTTON DATA-API // =============== - $(document).on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - Plugin.call($btn, 'toggle') - e.preventDefault() - }) + $(document) + .on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + Plugin.call($btn, 'toggle') + if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault() + }) + .on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) { + $(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type)) + }) }(jQuery); diff --git a/bower_components/bootstrap/js/carousel.js b/bower_components/bootstrap/js/carousel.js index b7da1ba..6b2f1c4 100644 --- a/bower_components/bootstrap/js/carousel.js +++ b/bower_components/bootstrap/js/carousel.js @@ -1,8 +1,8 @@ /* ======================================================================== - * Bootstrap: carousel.js v3.2.0 + * Bootstrap: carousel.js v3.3.5 * http://getbootstrap.com/javascript/#carousel * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. + * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ @@ -14,29 +14,35 @@ // ========================= var Carousel = function (element, options) { - this.$element = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this)) + this.$element = $(element) this.$indicators = this.$element.find('.carousel-indicators') this.options = options - this.paused = - this.sliding = - this.interval = - this.$active = + this.paused = null + this.sliding = null + this.interval = null + this.$active = null this.$items = null - this.options.pause == 'hover' && this.$element + this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this)) + + this.options.pause == 'hover' && !('ontouchstart' in document.documentElement) && this.$element .on('mouseenter.bs.carousel', $.proxy(this.pause, this)) .on('mouseleave.bs.carousel', $.proxy(this.cycle, this)) } - Carousel.VERSION = '3.2.0' + Carousel.VERSION = '3.3.5' + + Carousel.TRANSITION_DURATION = 600 Carousel.DEFAULTS = { interval: 5000, pause: 'hover', - wrap: true + wrap: true, + keyboard: true } Carousel.prototype.keydown = function (e) { + if (/input|textarea/i.test(e.target.tagName)) return switch (e.which) { case 37: this.prev(); break case 39: this.next(); break @@ -63,6 +69,16 @@ return this.$items.index(item || this.$active) } + Carousel.prototype.getItemForDirection = function (direction, active) { + var activeIndex = this.getItemIndex(active) + var willWrap = (direction == 'prev' && activeIndex === 0) + || (direction == 'next' && activeIndex == (this.$items.length - 1)) + if (willWrap && !this.options.wrap) return active + var delta = direction == 'prev' ? -1 : 1 + var itemIndex = (activeIndex + delta) % this.$items.length + return this.$items.eq(itemIndex) + } + Carousel.prototype.to = function (pos) { var that = this var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active')) @@ -72,7 +88,7 @@ if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid" if (activeIndex == pos) return this.pause().cycle() - return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + return this.slide(pos > activeIndex ? 'next' : 'prev', this.$items.eq(pos)) } Carousel.prototype.pause = function (e) { @@ -100,17 +116,11 @@ Carousel.prototype.slide = function (type, next) { var $active = this.$element.find('.item.active') - var $next = next || $active[type]() + var $next = next || this.getItemForDirection(type, $active) var isCycling = this.interval var direction = type == 'next' ? 'left' : 'right' - var fallback = type == 'next' ? 'first' : 'last' var that = this - if (!$next.length) { - if (!this.options.wrap) return - $next = this.$element.find('.item')[fallback]() - } - if ($next.hasClass('active')) return (this.sliding = false) var relatedTarget = $next[0] @@ -146,7 +156,7 @@ that.$element.trigger(slidEvent) }, 0) }) - .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000) + .emulateTransitionEnd(Carousel.TRANSITION_DURATION) } else { $active.removeClass('active') $next.addClass('active') @@ -195,7 +205,7 @@ // CAROUSEL DATA-API // ================= - $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var clickHandler = function (e) { var href var $this = $(this) var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7 @@ -211,7 +221,11 @@ } e.preventDefault() - }) + } + + $(document) + .on('click.bs.carousel.data-api', '[data-slide]', clickHandler) + .on('click.bs.carousel.data-api', '[data-slide-to]', clickHandler) $(window).on('load', function () { $('[data-ride="carousel"]').each(function () { diff --git a/bower_components/bootstrap/js/collapse.js b/bower_components/bootstrap/js/collapse.js index e4e6d79..329e535 100644 --- a/bower_components/bootstrap/js/collapse.js +++ b/bower_components/bootstrap/js/collapse.js @@ -1,8 +1,8 @@ /* ======================================================================== - * Bootstrap: collapse.js v3.2.0 + * Bootstrap: collapse.js v3.3.5 * http://getbootstrap.com/javascript/#collapse * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. + * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ @@ -16,13 +16,22 @@ var Collapse = function (element, options) { this.$element = $(element) this.options = $.extend({}, Collapse.DEFAULTS, options) + this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' + + '[data-toggle="collapse"][data-target="#' + element.id + '"]') this.transitioning = null - if (this.options.parent) this.$parent = $(this.options.parent) + if (this.options.parent) { + this.$parent = this.getParent() + } else { + this.addAriaAndCollapsedClass(this.$element, this.$trigger) + } + if (this.options.toggle) this.toggle() } - Collapse.VERSION = '3.2.0' + Collapse.VERSION = '3.3.5' + + Collapse.TRANSITION_DURATION = 350 Collapse.DEFAULTS = { toggle: true @@ -36,17 +45,21 @@ Collapse.prototype.show = function () { if (this.transitioning || this.$element.hasClass('in')) return + var activesData + var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing') + + if (actives && actives.length) { + activesData = actives.data('bs.collapse') + if (activesData && activesData.transitioning) return + } + var startEvent = $.Event('show.bs.collapse') this.$element.trigger(startEvent) if (startEvent.isDefaultPrevented()) return - var actives = this.$parent && this.$parent.find('> .panel > .in') - if (actives && actives.length) { - var hasData = actives.data('bs.collapse') - if (hasData && hasData.transitioning) return Plugin.call(actives, 'hide') - hasData || actives.data('bs.collapse', null) + activesData || actives.data('bs.collapse', null) } var dimension = this.dimension() @@ -54,6 +67,11 @@ this.$element .removeClass('collapse') .addClass('collapsing')[dimension](0) + .attr('aria-expanded', true) + + this.$trigger + .removeClass('collapsed') + .attr('aria-expanded', true) this.transitioning = 1 @@ -72,7 +90,7 @@ this.$element .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize]) + .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize]) } Collapse.prototype.hide = function () { @@ -88,17 +106,21 @@ this.$element .addClass('collapsing') - .removeClass('collapse') - .removeClass('in') + .removeClass('collapse in') + .attr('aria-expanded', false) + + this.$trigger + .addClass('collapsed') + .attr('aria-expanded', false) this.transitioning = 1 var complete = function () { this.transitioning = 0 this.$element - .trigger('hidden.bs.collapse') .removeClass('collapsing') .addClass('collapse') + .trigger('hidden.bs.collapse') } if (!$.support.transition) return complete.call(this) @@ -106,13 +128,40 @@ this.$element [dimension](0) .one('bsTransitionEnd', $.proxy(complete, this)) - .emulateTransitionEnd(350) + .emulateTransitionEnd(Collapse.TRANSITION_DURATION) } Collapse.prototype.toggle = function () { this[this.$element.hasClass('in') ? 'hide' : 'show']() } + Collapse.prototype.getParent = function () { + return $(this.options.parent) + .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]') + .each($.proxy(function (i, element) { + var $element = $(element) + this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element) + }, this)) + .end() + } + + Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) { + var isOpen = $element.hasClass('in') + + $element.attr('aria-expanded', isOpen) + $trigger + .toggleClass('collapsed', !isOpen) + .attr('aria-expanded', isOpen) + } + + function getTargetFromTrigger($trigger) { + var href + var target = $trigger.attr('data-target') + || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 + + return $(target) + } + // COLLAPSE PLUGIN DEFINITION // ========================== @@ -123,7 +172,7 @@ var data = $this.data('bs.collapse') var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) - if (!data && options.toggle && option == 'show') option = !option + if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) if (typeof option == 'string') data[option]() }) @@ -148,21 +197,13 @@ // ================= $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) { - var href var $this = $(this) - var target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7 - var $target = $(target) + + if (!$this.attr('data-target')) e.preventDefault() + + var $target = getTargetFromTrigger($this) var data = $target.data('bs.collapse') var option = data ? 'toggle' : $this.data() - var parent = $this.attr('data-parent') - var $parent = parent && $(parent) - - if (!data || !data.transitioning) { - if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed') - $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') - } Plugin.call($target, option) }) diff --git a/bower_components/bootstrap/js/dropdown.js b/bower_components/bootstrap/js/dropdown.js index 88f118c..bc4d373 100644 --- a/bower_components/bootstrap/js/dropdown.js +++ b/bower_components/bootstrap/js/dropdown.js @@ -1,8 +1,8 @@ /* ======================================================================== - * Bootstrap: dropdown.js v3.2.0 + * Bootstrap: dropdown.js v3.3.5 * http://getbootstrap.com/javascript/#dropdowns * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. + * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ @@ -19,7 +19,41 @@ $(element).on('click.bs.dropdown', this.toggle) } - Dropdown.VERSION = '3.2.0' + Dropdown.VERSION = '3.3.5' + + function getParent($this) { + var selector = $this.attr('data-target') + + if (!selector) { + selector = $this.attr('href') + selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } + + var $parent = selector && $(selector) + + return $parent && $parent.length ? $parent : $this.parent() + } + + function clearMenus(e) { + if (e && e.which === 3) return + $(backdrop).remove() + $(toggle).each(function () { + var $this = $(this) + var $parent = getParent($this) + var relatedTarget = { relatedTarget: this } + + if (!$parent.hasClass('open')) return + + if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return + + $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) + + if (e.isDefaultPrevented()) return + + $this.attr('aria-expanded', 'false') + $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget) + }) + } Dropdown.prototype.toggle = function (e) { var $this = $(this) @@ -34,7 +68,10 @@ if (!isActive) { if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { // if mobile we use a backdrop because click events don't delegate - $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus) + $(document.createElement('div')) + .addClass('dropdown-backdrop') + .insertAfter($(this)) + .on('click', clearMenus) } var relatedTarget = { relatedTarget: this } @@ -42,7 +79,9 @@ if (e.isDefaultPrevented()) return - $this.trigger('focus') + $this + .trigger('focus') + .attr('aria-expanded', 'true') $parent .toggleClass('open') @@ -53,7 +92,7 @@ } Dropdown.prototype.keydown = function (e) { - if (!/(38|40|27)/.test(e.keyCode)) return + if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return var $this = $(this) @@ -65,51 +104,25 @@ var $parent = getParent($this) var isActive = $parent.hasClass('open') - if (!isActive || (isActive && e.keyCode == 27)) { + if (!isActive && e.which != 27 || isActive && e.which == 27) { if (e.which == 27) $parent.find(toggle).trigger('focus') return $this.trigger('click') } - var desc = ' li:not(.divider):visible a' - var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc) + var desc = ' li:not(.disabled):visible a' + var $items = $parent.find('.dropdown-menu' + desc) if (!$items.length) return - var index = $items.index($items.filter(':focus')) + var index = $items.index(e.target) - if (e.keyCode == 38 && index > 0) index-- // up - if (e.keyCode == 40 && index < $items.length - 1) index++ // down - if (!~index) index = 0 + if (e.which == 38 && index > 0) index-- // up + if (e.which == 40 && index < $items.length - 1) index++ // down + if (!~index) index = 0 $items.eq(index).trigger('focus') } - function clearMenus(e) { - if (e && e.which === 3) return - $(backdrop).remove() - $(toggle).each(function () { - var $parent = getParent($(this)) - var relatedTarget = { relatedTarget: this } - if (!$parent.hasClass('open')) return - $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget)) - if (e.isDefaultPrevented()) return - $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget) - }) - } - - function getParent($this) { - var selector = $this.attr('data-target') - - if (!selector) { - selector = $this.attr('href') - selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } - - var $parent = selector && $(selector) - - return $parent && $parent.length ? $parent : $this.parent() - } - // DROPDOWN PLUGIN DEFINITION // ========================== @@ -146,6 +159,7 @@ .on('click.bs.dropdown.data-api', clearMenus) .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() }) .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle) - .on('keydown.bs.dropdown.data-api', toggle + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown) + .on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown) + .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown) }(jQuery); diff --git a/bower_components/bootstrap/js/modal.js b/bower_components/bootstrap/js/modal.js index 29eedf1..d50a856 100644 --- a/bower_components/bootstrap/js/modal.js +++ b/bower_components/bootstrap/js/modal.js @@ -1,8 +1,8 @@ /* ======================================================================== - * Bootstrap: modal.js v3.2.0 + * Bootstrap: modal.js v3.3.5 * http://getbootstrap.com/javascript/#modals * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. + * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ @@ -14,12 +14,15 @@ // ====================== var Modal = function (element, options) { - this.options = options - this.$body = $(document.body) - this.$element = $(element) - this.$backdrop = - this.isShown = null - this.scrollbarWidth = 0 + this.options = options + this.$body = $(document.body) + this.$element = $(element) + this.$dialog = this.$element.find('.modal-dialog') + this.$backdrop = null + this.isShown = null + this.originalBodyPad = null + this.scrollbarWidth = 0 + this.ignoreBackdropClick = false if (this.options.remote) { this.$element @@ -30,7 +33,10 @@ } } - Modal.VERSION = '3.2.0' + Modal.VERSION = '3.3.5' + + Modal.TRANSITION_DURATION = 300 + Modal.BACKDROP_TRANSITION_DURATION = 150 Modal.DEFAULTS = { backdrop: true, @@ -53,13 +59,20 @@ this.isShown = true this.checkScrollbar() + this.setScrollbar() this.$body.addClass('modal-open') - this.setScrollbar() this.escape() + this.resize() this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this)) + this.$dialog.on('mousedown.dismiss.bs.modal', function () { + that.$element.one('mouseup.dismiss.bs.modal', function (e) { + if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true + }) + }) + this.backdrop(function () { var transition = $.support.transition && that.$element.hasClass('fade') @@ -71,24 +84,24 @@ .show() .scrollTop(0) + that.adjustDialog() + if (transition) { that.$element[0].offsetWidth // force reflow } - that.$element - .addClass('in') - .attr('aria-hidden', false) + that.$element.addClass('in') that.enforceFocus() var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget }) transition ? - that.$element.find('.modal-dialog') // wait for modal to slide in + that.$dialog // wait for modal to slide in .one('bsTransitionEnd', function () { that.$element.trigger('focus').trigger(e) }) - .emulateTransitionEnd(300) : + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : that.$element.trigger('focus').trigger(e) }) } @@ -104,22 +117,22 @@ this.isShown = false - this.$body.removeClass('modal-open') - - this.resetScrollbar() this.escape() + this.resize() $(document).off('focusin.bs.modal') this.$element .removeClass('in') - .attr('aria-hidden', true) .off('click.dismiss.bs.modal') + .off('mouseup.dismiss.bs.modal') + + this.$dialog.off('mousedown.dismiss.bs.modal') $.support.transition && this.$element.hasClass('fade') ? this.$element .one('bsTransitionEnd', $.proxy(this.hideModal, this)) - .emulateTransitionEnd(300) : + .emulateTransitionEnd(Modal.TRANSITION_DURATION) : this.hideModal() } @@ -135,11 +148,19 @@ Modal.prototype.escape = function () { if (this.isShown && this.options.keyboard) { - this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) { + this.$element.on('keydown.dismiss.bs.modal', $.proxy(function (e) { e.which == 27 && this.hide() }, this)) } else if (!this.isShown) { - this.$element.off('keyup.dismiss.bs.modal') + this.$element.off('keydown.dismiss.bs.modal') + } + } + + Modal.prototype.resize = function () { + if (this.isShown) { + $(window).on('resize.bs.modal', $.proxy(this.handleUpdate, this)) + } else { + $(window).off('resize.bs.modal') } } @@ -147,6 +168,9 @@ var that = this this.$element.hide() this.backdrop(function () { + that.$body.removeClass('modal-open') + that.resetAdjustments() + that.resetScrollbar() that.$element.trigger('hidden.bs.modal') }) } @@ -163,14 +187,19 @@ if (this.isShown && this.options.backdrop) { var doAnimate = $.support.transition && animate - this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />') + this.$backdrop = $(document.createElement('div')) + .addClass('modal-backdrop ' + animate) .appendTo(this.$body) this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) { + if (this.ignoreBackdropClick) { + this.ignoreBackdropClick = false + return + } if (e.target !== e.currentTarget) return this.options.backdrop == 'static' - ? this.$element[0].focus.call(this.$element[0]) - : this.hide.call(this) + ? this.$element[0].focus() + : this.hide() }, this)) if (doAnimate) this.$backdrop[0].offsetWidth // force reflow @@ -182,7 +211,7 @@ doAnimate ? this.$backdrop .one('bsTransitionEnd', callback) - .emulateTransitionEnd(150) : + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callback() } else if (!this.isShown && this.$backdrop) { @@ -195,7 +224,7 @@ $.support.transition && this.$element.hasClass('fade') ? this.$backdrop .one('bsTransitionEnd', callbackRemove) - .emulateTransitionEnd(150) : + .emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callbackRemove() } else if (callback) { @@ -203,18 +232,46 @@ } } + // these following methods are used to handle overflowing modals + + Modal.prototype.handleUpdate = function () { + this.adjustDialog() + } + + Modal.prototype.adjustDialog = function () { + var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight + + this.$element.css({ + paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : '', + paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : '' + }) + } + + Modal.prototype.resetAdjustments = function () { + this.$element.css({ + paddingLeft: '', + paddingRight: '' + }) + } + Modal.prototype.checkScrollbar = function () { - if (document.body.clientWidth >= window.innerWidth) return - this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar() + var fullWindowWidth = window.innerWidth + if (!fullWindowWidth) { // workaround for missing window.innerWidth in IE8 + var documentElementRect = document.documentElement.getBoundingClientRect() + fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left) + } + this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth + this.scrollbarWidth = this.measureScrollbar() } Modal.prototype.setScrollbar = function () { var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10) - if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) + this.originalBodyPad = document.body.style.paddingRight || '' + if (this.bodyIsOverflowing) this.$body.css('padding-right', bodyPad + this.scrollbarWidth) } Modal.prototype.resetScrollbar = function () { - this.$body.css('padding-right', '') + this.$body.css('padding-right', this.originalBodyPad) } Modal.prototype.measureScrollbar = function () { // thx walsh diff --git a/bower_components/bootstrap/js/popover.js b/bower_components/bootstrap/js/popover.js index 825e1b3..aef22d1 100644 --- a/bower_components/bootstrap/js/popover.js +++ b/bower_components/bootstrap/js/popover.js @@ -1,8 +1,8 @@ /* ======================================================================== - * Bootstrap: popover.js v3.2.0 + * Bootstrap: popover.js v3.3.5 * http://getbootstrap.com/javascript/#popovers * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. + * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ @@ -19,7 +19,7 @@ if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js') - Popover.VERSION = '3.2.0' + Popover.VERSION = '3.3.5' Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, { placement: 'right', @@ -46,7 +46,7 @@ var content = this.getContent() $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title) - $tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events + $tip.find('.popover-content').children().detach().end()[ // we use append for html objects to maintain js events this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text' ](content) @@ -75,11 +75,6 @@ return (this.$arrow = this.$arrow || this.tip().find('.arrow')) } - Popover.prototype.tip = function () { - if (!this.$tip) this.$tip = $(this.options.template) - return this.$tip - } - // POPOVER PLUGIN DEFINITION // ========================= @@ -90,7 +85,7 @@ var data = $this.data('bs.popover') var options = typeof option == 'object' && option - if (!data && option == 'destroy') return + if (!data && /destroy|hide/.test(option)) return if (!data) $this.data('bs.popover', (data = new Popover(this, options))) if (typeof option == 'string') data[option]() }) diff --git a/bower_components/bootstrap/js/scrollspy.js b/bower_components/bootstrap/js/scrollspy.js index db23787..7208e25 100644 --- a/bower_components/bootstrap/js/scrollspy.js +++ b/bower_components/bootstrap/js/scrollspy.js @@ -1,8 +1,8 @@ /* ======================================================================== - * Bootstrap: scrollspy.js v3.2.0 + * Bootstrap: scrollspy.js v3.3.5 * http://getbootstrap.com/javascript/#scrollspy * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. + * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ @@ -14,10 +14,8 @@ // ========================== function ScrollSpy(element, options) { - var process = $.proxy(this.process, this) - - this.$body = $('body') - this.$scrollElement = $(element).is('body') ? $(window) : $(element) + this.$body = $(document.body) + this.$scrollElement = $(element).is(document.body) ? $(window) : $(element) this.options = $.extend({}, ScrollSpy.DEFAULTS, options) this.selector = (this.options.target || '') + ' .nav li > a' this.offsets = [] @@ -25,12 +23,12 @@ this.activeTarget = null this.scrollHeight = 0 - this.$scrollElement.on('scroll.bs.scrollspy', process) + this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this)) this.refresh() this.process() } - ScrollSpy.VERSION = '3.2.0' + ScrollSpy.VERSION = '3.3.5' ScrollSpy.DEFAULTS = { offset: 10 @@ -41,20 +39,19 @@ } ScrollSpy.prototype.refresh = function () { - var offsetMethod = 'offset' - var offsetBase = 0 + var that = this + var offsetMethod = 'offset' + var offsetBase = 0 + + this.offsets = [] + this.targets = [] + this.scrollHeight = this.getScrollHeight() if (!$.isWindow(this.$scrollElement[0])) { offsetMethod = 'position' offsetBase = this.$scrollElement.scrollTop() } - this.offsets = [] - this.targets = [] - this.scrollHeight = this.getScrollHeight() - - var self = this - this.$body .find(this.selector) .map(function () { @@ -69,8 +66,8 @@ }) .sort(function (a, b) { return a[0] - b[0] }) .each(function () { - self.offsets.push(this[0]) - self.targets.push(this[1]) + that.offsets.push(this[0]) + that.targets.push(this[1]) }) } @@ -91,14 +88,15 @@ return activeTarget != (i = targets[targets.length - 1]) && this.activate(i) } - if (activeTarget && scrollTop <= offsets[0]) { - return activeTarget != (i = targets[0]) && this.activate(i) + if (activeTarget && scrollTop < offsets[0]) { + this.activeTarget = null + return this.clear() } for (i = offsets.length; i--;) { activeTarget != targets[i] && scrollTop >= offsets[i] - && (!offsets[i + 1] || scrollTop <= offsets[i + 1]) + && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1]) && this.activate(targets[i]) } } @@ -106,13 +104,11 @@ ScrollSpy.prototype.activate = function (target) { this.activeTarget = target - $(this.selector) - .parentsUntil(this.options.target, '.active') - .removeClass('active') + this.clear() var selector = this.selector + - '[data-target="' + target + '"],' + - this.selector + '[href="' + target + '"]' + '[data-target="' + target + '"],' + + this.selector + '[href="' + target + '"]' var active = $(selector) .parents('li') @@ -127,6 +123,12 @@ active.trigger('activate.bs.scrollspy') } + ScrollSpy.prototype.clear = function () { + $(this.selector) + .parentsUntil(this.options.target, '.active') + .removeClass('active') + } + // SCROLLSPY PLUGIN DEFINITION // =========================== diff --git a/bower_components/bootstrap/js/tab.js b/bower_components/bootstrap/js/tab.js index c0e1e46..8d5361f 100644 --- a/bower_components/bootstrap/js/tab.js +++ b/bower_components/bootstrap/js/tab.js @@ -1,8 +1,8 @@ /* ======================================================================== - * Bootstrap: tab.js v3.2.0 + * Bootstrap: tab.js v3.3.5 * http://getbootstrap.com/javascript/#tabs * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. + * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ @@ -14,10 +14,14 @@ // ==================== var Tab = function (element) { + // jscs:disable requireDollarBeforejQueryAssignment this.element = $(element) + // jscs:enable requireDollarBeforejQueryAssignment } - Tab.VERSION = '3.2.0' + Tab.VERSION = '3.3.5' + + Tab.TRANSITION_DURATION = 150 Tab.prototype.show = function () { var $this = this.element @@ -31,22 +35,30 @@ if ($this.parent('li').hasClass('active')) return - var previous = $ul.find('.active:last a')[0] - var e = $.Event('show.bs.tab', { - relatedTarget: previous + var $previous = $ul.find('.active:last a') + var hideEvent = $.Event('hide.bs.tab', { + relatedTarget: $this[0] + }) + var showEvent = $.Event('show.bs.tab', { + relatedTarget: $previous[0] }) - $this.trigger(e) + $previous.trigger(hideEvent) + $this.trigger(showEvent) - if (e.isDefaultPrevented()) return + if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return var $target = $(selector) this.activate($this.closest('li'), $ul) this.activate($target, $target.parent(), function () { + $previous.trigger({ + type: 'hidden.bs.tab', + relatedTarget: $this[0] + }) $this.trigger({ type: 'shown.bs.tab', - relatedTarget: previous + relatedTarget: $previous[0] }) }) } @@ -55,15 +67,21 @@ var $active = container.find('> .active') var transition = callback && $.support.transition - && $active.hasClass('fade') + && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length) function next() { $active .removeClass('active') .find('> .dropdown-menu > .active') - .removeClass('active') + .removeClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', false) - element.addClass('active') + element + .addClass('active') + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) if (transition) { element[0].offsetWidth // reflow for transition @@ -72,17 +90,22 @@ element.removeClass('fade') } - if (element.parent('.dropdown-menu')) { - element.closest('li.dropdown').addClass('active') + if (element.parent('.dropdown-menu').length) { + element + .closest('li.dropdown') + .addClass('active') + .end() + .find('[data-toggle="tab"]') + .attr('aria-expanded', true) } callback && callback() } - transition ? + $active.length && transition ? $active .one('bsTransitionEnd', next) - .emulateTransitionEnd(150) : + .emulateTransitionEnd(Tab.TRANSITION_DURATION) : next() $active.removeClass('in') @@ -120,9 +143,13 @@ // TAB DATA-API // ============ - $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) { + var clickHandler = function (e) { e.preventDefault() Plugin.call($(this), 'show') - }) + } + + $(document) + .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler) + .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler) }(jQuery); diff --git a/bower_components/bootstrap/js/tooltip.js b/bower_components/bootstrap/js/tooltip.js index 9cdb6c9..c3fe4b0 100644 --- a/bower_components/bootstrap/js/tooltip.js +++ b/bower_components/bootstrap/js/tooltip.js @@ -1,9 +1,9 @@ /* ======================================================================== - * Bootstrap: tooltip.js v3.2.0 + * Bootstrap: tooltip.js v3.3.5 * http://getbootstrap.com/javascript/#tooltip * Inspired by the original jQuery.tipsy by Jason Frame * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. + * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ @@ -15,17 +15,20 @@ // =============================== var Tooltip = function (element, options) { - this.type = - this.options = - this.enabled = - this.timeout = - this.hoverState = + this.type = null + this.options = null + this.enabled = null + this.timeout = null + this.hoverState = null this.$element = null + this.inState = null this.init('tooltip', element, options) } - Tooltip.VERSION = '3.2.0' + Tooltip.VERSION = '3.3.5' + + Tooltip.TRANSITION_DURATION = 150 Tooltip.DEFAULTS = { animation: true, @@ -48,7 +51,12 @@ this.type = type this.$element = $(element) this.options = this.getOptions(options) - this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport) + this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport)) + this.inState = { click: false, hover: false, focus: false } + + if (this.$element[0] instanceof document.constructor && !this.options.selector) { + throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!') + } var triggers = this.options.trigger.split(' ') @@ -108,6 +116,15 @@ $(obj.currentTarget).data('bs.' + this.type, self) } + if (obj instanceof $.Event) { + self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true + } + + if (self.tip().hasClass('in') || self.hoverState == 'in') { + self.hoverState = 'in' + return + } + clearTimeout(self.timeout) self.hoverState = 'in' @@ -119,6 +136,14 @@ }, self.options.delay.show) } + Tooltip.prototype.isInStateTrue = function () { + for (var key in this.inState) { + if (this.inState[key]) return true + } + + return false + } + Tooltip.prototype.leave = function (obj) { var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data('bs.' + this.type) @@ -128,6 +153,12 @@ $(obj.currentTarget).data('bs.' + this.type, self) } + if (obj instanceof $.Event) { + self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false + } + + if (self.isInStateTrue()) return + clearTimeout(self.timeout) self.hoverState = 'out' @@ -145,7 +176,7 @@ if (this.hasContent() && this.enabled) { this.$element.trigger(e) - var inDom = $.contains(document.documentElement, this.$element[0]) + var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]) if (e.isDefaultPrevented() || !inDom) return var that = this @@ -174,6 +205,7 @@ .data('bs.' + this.type, this) this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element) + this.$element.trigger('inserted.bs.' + this.type) var pos = this.getPosition() var actualWidth = $tip[0].offsetWidth @@ -181,13 +213,12 @@ if (autoPlace) { var orgPlacement = placement - var $parent = this.$element.parent() - var parentDim = this.getPosition($parent) + var viewportDim = this.getPosition(this.$viewport) - placement = placement == 'bottom' && pos.top + pos.height + actualHeight - parentDim.scroll > parentDim.height ? 'top' : - placement == 'top' && pos.top - parentDim.scroll - actualHeight < 0 ? 'bottom' : - placement == 'right' && pos.right + actualWidth > parentDim.width ? 'left' : - placement == 'left' && pos.left - actualWidth < parentDim.left ? 'right' : + placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' : + placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' : + placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' : + placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' : placement $tip @@ -200,14 +231,17 @@ this.applyPlacement(calculatedOffset, placement) var complete = function () { + var prevHoverState = that.hoverState that.$element.trigger('shown.bs.' + that.type) that.hoverState = null + + if (prevHoverState == 'out') that.leave(that) } $.support.transition && this.$tip.hasClass('fade') ? $tip .one('bsTransitionEnd', complete) - .emulateTransitionEnd(150) : + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete() } } @@ -225,8 +259,8 @@ if (isNaN(marginTop)) marginTop = 0 if (isNaN(marginLeft)) marginLeft = 0 - offset.top = offset.top + marginTop - offset.left = offset.left + marginLeft + offset.top += marginTop + offset.left += marginLeft // $.fn.offset doesn't round pixel values // so we use setOffset directly with our own function B-0 @@ -254,16 +288,18 @@ if (delta.left) offset.left += delta.left else offset.top += delta.top - var arrowDelta = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight - var arrowPosition = delta.left ? 'left' : 'top' - var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight' + var isVertical = /top|bottom/.test(placement) + var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight + var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight' $tip.offset(offset) - this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition) + this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical) } - Tooltip.prototype.replaceArrow = function (delta, dimension, position) { - this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '') + Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) { + this.arrow() + .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%') + .css(isVertical ? 'top' : 'left', '') } Tooltip.prototype.setContent = function () { @@ -274,16 +310,17 @@ $tip.removeClass('fade in top bottom left right') } - Tooltip.prototype.hide = function () { + Tooltip.prototype.hide = function (callback) { var that = this - var $tip = this.tip() + var $tip = $(this.$tip) var e = $.Event('hide.bs.' + this.type) - this.$element.removeAttr('aria-describedby') - function complete() { if (that.hoverState != 'in') $tip.detach() - that.$element.trigger('hidden.bs.' + that.type) + that.$element + .removeAttr('aria-describedby') + .trigger('hidden.bs.' + that.type) + callback && callback() } this.$element.trigger(e) @@ -292,10 +329,10 @@ $tip.removeClass('in') - $.support.transition && this.$tip.hasClass('fade') ? + $.support.transition && $tip.hasClass('fade') ? $tip .one('bsTransitionEnd', complete) - .emulateTransitionEnd(150) : + .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete() this.hoverState = null @@ -305,7 +342,7 @@ Tooltip.prototype.fixTitle = function () { var $e = this.$element - if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') { + if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') { $e.attr('data-original-title', $e.attr('title') || '').attr('title', '') } } @@ -316,20 +353,27 @@ Tooltip.prototype.getPosition = function ($element) { $element = $element || this.$element + var el = $element[0] var isBody = el.tagName == 'BODY' - return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, { - scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(), - width: isBody ? $(window).width() : $element.outerWidth(), - height: isBody ? $(window).height() : $element.outerHeight() - }, isBody ? { top: 0, left: 0 } : $element.offset()) + + var elRect = el.getBoundingClientRect() + if (elRect.width == null) { + // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093 + elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top }) + } + var elOffset = isBody ? { top: 0, left: 0 } : $element.offset() + var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() } + var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null + + return $.extend({}, elRect, scroll, outerDims, elOffset) } Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) { - return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : - placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : + return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } : + placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } : placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } : - /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } + /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width } } @@ -353,7 +397,7 @@ var rightEdgeOffset = pos.left + viewportPadding + actualWidth if (leftEdgeOffset < viewportDimensions.left) { // left overflow delta.left = viewportDimensions.left - leftEdgeOffset - } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow + } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset } } @@ -379,21 +423,19 @@ } Tooltip.prototype.tip = function () { - return (this.$tip = this.$tip || $(this.options.template)) + if (!this.$tip) { + this.$tip = $(this.options.template) + if (this.$tip.length != 1) { + throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!') + } + } + return this.$tip } Tooltip.prototype.arrow = function () { return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow')) } - Tooltip.prototype.validate = function () { - if (!this.$element[0].parentNode) { - this.hide() - this.$element = null - this.options = null - } - } - Tooltip.prototype.enable = function () { this.enabled = true } @@ -416,12 +458,27 @@ } } - self.tip().hasClass('in') ? self.leave(self) : self.enter(self) + if (e) { + self.inState.click = !self.inState.click + if (self.isInStateTrue()) self.enter(self) + else self.leave(self) + } else { + self.tip().hasClass('in') ? self.leave(self) : self.enter(self) + } } Tooltip.prototype.destroy = function () { + var that = this clearTimeout(this.timeout) - this.hide().$element.off('.' + this.type).removeData('bs.' + this.type) + this.hide(function () { + that.$element.off('.' + that.type).removeData('bs.' + that.type) + if (that.$tip) { + that.$tip.detach() + } + that.$tip = null + that.$arrow = null + that.$viewport = null + }) } @@ -434,7 +491,7 @@ var data = $this.data('bs.tooltip') var options = typeof option == 'object' && option - if (!data && option == 'destroy') return + if (!data && /destroy|hide/.test(option)) return if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options))) if (typeof option == 'string') data[option]() }) diff --git a/bower_components/bootstrap/js/transition.js b/bower_components/bootstrap/js/transition.js index 83f85bf..cd89fc4 100644 --- a/bower_components/bootstrap/js/transition.js +++ b/bower_components/bootstrap/js/transition.js @@ -1,8 +1,8 @@ /* ======================================================================== - * Bootstrap: transition.js v3.2.0 + * Bootstrap: transition.js v3.3.5 * http://getbootstrap.com/javascript/#transitions * ======================================================================== - * Copyright 2011-2014 Twitter, Inc. + * Copyright 2011-2015 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) * ======================================================================== */ diff --git a/bower_components/bootstrap/less/.csscomb.json b/bower_components/bootstrap/less/.csscomb.json new file mode 100644 index 0000000..40695a4 --- /dev/null +++ b/bower_components/bootstrap/less/.csscomb.json @@ -0,0 +1,304 @@ +{ + "always-semicolon": true, + "block-indent": 2, + "color-case": "lower", + "color-shorthand": true, + "element-case": "lower", + "eof-newline": true, + "leading-zero": false, + "remove-empty-rulesets": true, + "space-after-colon": 1, + "space-after-combinator": 1, + "space-before-selector-delimiter": 0, + "space-between-declarations": "\n", + "space-after-opening-brace": "\n", + "space-before-closing-brace": "\n", + "space-before-colon": 0, + "space-before-combinator": 1, + "space-before-opening-brace": 1, + "strip-spaces": true, + "unitless-zero": true, + "vendor-prefix-align": true, + "sort-order": [ + [ + "position", + "top", + "right", + "bottom", + "left", + "z-index", + "display", + "float", + "width", + "min-width", + "max-width", + "height", + "min-height", + "max-height", + "-webkit-box-sizing", + "-moz-box-sizing", + "box-sizing", + "-webkit-appearance", + "padding", + "padding-top", + "padding-right", + "padding-bottom", + "padding-left", + "margin", + "margin-top", + "margin-right", + "margin-bottom", + "margin-left", + "overflow", + "overflow-x", + "overflow-y", + "-webkit-overflow-scrolling", + "-ms-overflow-x", + "-ms-overflow-y", + "-ms-overflow-style", + "clip", + "clear", + "font", + "font-family", + "font-size", + "font-style", + "font-weight", + "font-variant", + "font-size-adjust", + "font-stretch", + "font-effect", + "font-emphasize", + "font-emphasize-position", + "font-emphasize-style", + "font-smooth", + "-webkit-hyphens", + "-moz-hyphens", + "hyphens", + "line-height", + "color", + "text-align", + "-webkit-text-align-last", + "-moz-text-align-last", + "-ms-text-align-last", + "text-align-last", + "text-emphasis", + "text-emphasis-color", + "text-emphasis-style", + "text-emphasis-position", + "text-decoration", + "text-indent", + "text-justify", + "text-outline", + "-ms-text-overflow", + "text-overflow", + "text-overflow-ellipsis", + "text-overflow-mode", + "text-shadow", + "text-transform", + "text-wrap", + "-webkit-text-size-adjust", + "-ms-text-size-adjust", + "letter-spacing", + "-ms-word-break", + "word-break", + "word-spacing", + "-ms-word-wrap", + "word-wrap", + "-moz-tab-size", + "-o-tab-size", + "tab-size", + "white-space", + "vertical-align", + "list-style", + "list-style-position", + "list-style-type", + "list-style-image", + "pointer-events", + "-ms-touch-action", + "touch-action", + "cursor", + "visibility", + "zoom", + "flex-direction", + "flex-order", + "flex-pack", + "flex-align", + "table-layout", + "empty-cells", + "caption-side", + "border-spacing", + "border-collapse", + "content", + "quotes", + "counter-reset", + "counter-increment", + "resize", + "-webkit-user-select", + "-moz-user-select", + "-ms-user-select", + "-o-user-select", + "user-select", + "nav-index", + "nav-up", + "nav-right", + "nav-down", + "nav-left", + "background", + "background-color", + "background-image", + "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient", + "filter:progid:DXImageTransform.Microsoft.gradient", + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader", + "filter", + "background-repeat", + "background-attachment", + "background-position", + "background-position-x", + "background-position-y", + "-webkit-background-clip", + "-moz-background-clip", + "background-clip", + "background-origin", + "-webkit-background-size", + "-moz-background-size", + "-o-background-size", + "background-size", + "border", + "border-color", + "border-style", + "border-width", + "border-top", + "border-top-color", + "border-top-style", + "border-top-width", + "border-right", + "border-right-color", + "border-right-style", + "border-right-width", + "border-bottom", + "border-bottom-color", + "border-bottom-style", + "border-bottom-width", + "border-left", + "border-left-color", + "border-left-style", + "border-left-width", + "border-radius", + "border-top-left-radius", + "border-top-right-radius", + "border-bottom-right-radius", + "border-bottom-left-radius", + "-webkit-border-image", + "-moz-border-image", + "-o-border-image", + "border-image", + "-webkit-border-image-source", + "-moz-border-image-source", + "-o-border-image-source", + "border-image-source", + "-webkit-border-image-slice", + "-moz-border-image-slice", + "-o-border-image-slice", + "border-image-slice", + "-webkit-border-image-width", + "-moz-border-image-width", + "-o-border-image-width", + "border-image-width", + "-webkit-border-image-outset", + "-moz-border-image-outset", + "-o-border-image-outset", + "border-image-outset", + "-webkit-border-image-repeat", + "-moz-border-image-repeat", + "-o-border-image-repeat", + "border-image-repeat", + "outline", + "outline-width", + "outline-style", + "outline-color", + "outline-offset", + "-webkit-box-shadow", + "-moz-box-shadow", + "box-shadow", + "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity", + "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha", + "opacity", + "-ms-interpolation-mode", + "-webkit-transition", + "-moz-transition", + "-ms-transition", + "-o-transition", + "transition", + "-webkit-transition-delay", + "-moz-transition-delay", + "-ms-transition-delay", + "-o-transition-delay", + "transition-delay", + "-webkit-transition-timing-function", + "-moz-transition-timing-function", + "-ms-transition-timing-function", + "-o-transition-timing-function", + "transition-timing-function", + "-webkit-transition-duration", + "-moz-transition-duration", + "-ms-transition-duration", + "-o-transition-duration", + "transition-duration", + "-webkit-transition-property", + "-moz-transition-property", + "-ms-transition-property", + "-o-transition-property", + "transition-property", + "-webkit-transform", + "-moz-transform", + "-ms-transform", + "-o-transform", + "transform", + "-webkit-transform-origin", + "-moz-transform-origin", + "-ms-transform-origin", + "-o-transform-origin", + "transform-origin", + "-webkit-animation", + "-moz-animation", + "-ms-animation", + "-o-animation", + "animation", + "-webkit-animation-name", + "-moz-animation-name", + "-ms-animation-name", + "-o-animation-name", + "animation-name", + "-webkit-animation-duration", + "-moz-animation-duration", + "-ms-animation-duration", + "-o-animation-duration", + "animation-duration", + "-webkit-animation-play-state", + "-moz-animation-play-state", + "-ms-animation-play-state", + "-o-animation-play-state", + "animation-play-state", + "-webkit-animation-timing-function", + "-moz-animation-timing-function", + "-ms-animation-timing-function", + "-o-animation-timing-function", + "animation-timing-function", + "-webkit-animation-delay", + "-moz-animation-delay", + "-ms-animation-delay", + "-o-animation-delay", + "animation-delay", + "-webkit-animation-iteration-count", + "-moz-animation-iteration-count", + "-ms-animation-iteration-count", + "-o-animation-iteration-count", + "animation-iteration-count", + "-webkit-animation-direction", + "-moz-animation-direction", + "-ms-animation-direction", + "-o-animation-direction", + "animation-direction" + ] + ] +} diff --git a/bower_components/bootstrap/less/.csslintrc b/bower_components/bootstrap/less/.csslintrc new file mode 100644 index 0000000..005b862 --- /dev/null +++ b/bower_components/bootstrap/less/.csslintrc @@ -0,0 +1,19 @@ +{ + "adjoining-classes": false, + "box-sizing": false, + "box-model": false, + "compatible-vendor-prefixes": false, + "floats": false, + "font-sizes": false, + "gradients": false, + "important": false, + "known-properties": false, + "outline-none": false, + "qualified-headings": false, + "regex-selectors": false, + "shorthand": false, + "text-indent": false, + "unique-headings": false, + "universal-selector": false, + "unqualified-attributes": false +} diff --git a/bower_components/bootstrap/less/alerts.less b/bower_components/bootstrap/less/alerts.less index df070b8..c4199db 100644 --- a/bower_components/bootstrap/less/alerts.less +++ b/bower_components/bootstrap/less/alerts.less @@ -18,6 +18,7 @@ // Specified for the h4 to prevent conflicts of changing @headings-color color: inherit; } + // Provide class for links that match alerts .alert-link { font-weight: @alert-link-font-weight; @@ -28,6 +29,7 @@ > ul { margin-bottom: 0; } + > p + p { margin-top: 5px; } @@ -57,12 +59,15 @@ .alert-success { .alert-variant(@alert-success-bg; @alert-success-border; @alert-success-text); } + .alert-info { .alert-variant(@alert-info-bg; @alert-info-border; @alert-info-text); } + .alert-warning { .alert-variant(@alert-warning-bg; @alert-warning-border; @alert-warning-text); } + .alert-danger { .alert-variant(@alert-danger-bg; @alert-danger-border; @alert-danger-text); } diff --git a/bower_components/bootstrap/less/badges.less b/bower_components/bootstrap/less/badges.less index 20624f3..6ee16dc 100644 --- a/bower_components/bootstrap/less/badges.less +++ b/bower_components/bootstrap/less/badges.less @@ -12,7 +12,7 @@ font-weight: @badge-font-weight; color: @badge-color; line-height: @badge-line-height; - vertical-align: baseline; + vertical-align: middle; white-space: nowrap; text-align: center; background-color: @badge-bg; @@ -28,7 +28,9 @@ position: relative; top: -1px; } - .btn-xs & { + + .btn-xs &, + .btn-group-xs > .btn & { top: 0; padding: 1px 5px; } @@ -44,11 +46,20 @@ } // Account for badges in navs - a.list-group-item.active > &, + .list-group-item.active > &, .nav-pills > .active > a > & { color: @badge-active-color; background-color: @badge-active-bg; } + + .list-group-item > & { + float: right; + } + + .list-group-item > & + & { + margin-right: 5px; + } + .nav-pills > li > a > & { margin-left: 3px; } diff --git a/bower_components/bootstrap/less/bootstrap.less b/bower_components/bootstrap/less/bootstrap.less index 61b7747..4b9916e 100644 --- a/bower_components/bootstrap/less/bootstrap.less +++ b/bower_components/bootstrap/less/bootstrap.less @@ -1,3 +1,9 @@ +/*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + // Core variables and mixins @import "variables.less"; @import "mixins.less"; diff --git a/bower_components/bootstrap/less/button-groups.less b/bower_components/bootstrap/less/button-groups.less index 7021ecd..6a0c5a8 100644 --- a/bower_components/bootstrap/less/button-groups.less +++ b/bower_components/bootstrap/less/button-groups.less @@ -18,10 +18,6 @@ &.active { z-index: 2; } - &:focus { - // Remove focus outline when dropdown JS adds it after closing the menu - outline: 0; - } } } @@ -40,6 +36,7 @@ margin-left: -5px; // Offset the first child's margin &:extend(.clearfix all); + .btn, .btn-group, .input-group { float: left; @@ -75,13 +72,13 @@ .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { border-radius: 0; } -.btn-group > .btn-group:first-child { +.btn-group > .btn-group:first-child:not(:last-child) { > .btn:last-child, > .dropdown-toggle { .border-right-radius(0); } } -.btn-group > .btn-group:last-child > .btn:first-child { +.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child { .border-left-radius(0); } @@ -176,11 +173,11 @@ border-radius: 0; } &:first-child:not(:last-child) { - border-top-right-radius: @border-radius-base; + border-top-right-radius: @btn-border-radius-base; .border-bottom-radius(0); } &:last-child:not(:first-child) { - border-bottom-left-radius: @border-radius-base; + border-bottom-left-radius: @btn-border-radius-base; .border-top-radius(0); } } @@ -198,7 +195,6 @@ } - // Justified button groups // ---------------------- @@ -226,15 +222,23 @@ // Checkbox and radio options // // In order to support the browser's form validation feedback, powered by the -// `required` attribute, we have to "hide" the inputs via `opacity`. We cannot -// use `display: none;` or `visibility: hidden;` as that also hides the popover. +// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use +// `display: none;` or `visibility: hidden;` as that also hides the popover. +// Simply visually hiding the inputs via `opacity` would leave them clickable in +// certain cases which is prevented by using `clip` and `pointer-events`. // This way, we ensure a DOM element is visible to position the popover from. // -// See https://github.com/twbs/bootstrap/pull/12794 for more. +// See https://github.com/twbs/bootstrap/pull/12794 and +// https://github.com/twbs/bootstrap/pull/14559 for more information. -[data-toggle="buttons"] > .btn > input[type="radio"], -[data-toggle="buttons"] > .btn > input[type="checkbox"] { - position: absolute; - z-index: -1; - .opacity(0); +[data-toggle="buttons"] { + > .btn, + > .btn-group > .btn { + input[type="radio"], + input[type="checkbox"] { + position: absolute; + clip: rect(0,0,0,0); + pointer-events: none; + } + } } diff --git a/bower_components/bootstrap/less/buttons.less b/bower_components/bootstrap/less/buttons.less index 492bdc6..9cbb8f4 100644 --- a/bower_components/bootstrap/less/buttons.less +++ b/bower_components/bootstrap/less/buttons.less @@ -12,23 +12,26 @@ font-weight: @btn-font-weight; text-align: center; vertical-align: middle; + touch-action: manipulation; cursor: pointer; background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 border: 1px solid transparent; white-space: nowrap; - .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base); + .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @btn-border-radius-base); .user-select(none); &, &:active, &.active { - &:focus { + &:focus, + &.focus { .tab-focus(); } } &:hover, - &:focus { + &:focus, + &.focus { color: @btn-default-color; text-decoration: none; } @@ -43,11 +46,17 @@ &.disabled, &[disabled], fieldset[disabled] & { - cursor: not-allowed; - pointer-events: none; // Future-proof disabling of clicks + cursor: @cursor-disabled; .opacity(.65); .box-shadow(none); } + + a& { + &.disabled, + fieldset[disabled] & { + pointer-events: none; // Future-proof disabling of clicks on `<a>` elements + } + } } @@ -85,11 +94,11 @@ .btn-link { color: @link-color; font-weight: normal; - cursor: pointer; border-radius: 0; &, &:active, + &.active, &[disabled], fieldset[disabled] & { background-color: transparent; @@ -104,7 +113,7 @@ &:hover, &:focus { color: @link-hover-color; - text-decoration: underline; + text-decoration: @link-hover-decoration; background-color: transparent; } &[disabled], @@ -123,14 +132,14 @@ .btn-lg { // line-height: ensure even-numbered height of button next to large input - .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large); + .button-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @btn-border-radius-large); } .btn-sm { // line-height: ensure proper height of button next to small input - .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small); + .button-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small); } .btn-xs { - .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small); + .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @btn-border-radius-small); } diff --git a/bower_components/bootstrap/less/carousel.less b/bower_components/bootstrap/less/carousel.less index 1644ddf..87ed696 100644 --- a/bower_components/bootstrap/less/carousel.less +++ b/bower_components/bootstrap/less/carousel.less @@ -24,6 +24,30 @@ &:extend(.img-responsive); line-height: 1; } + + // WebKit CSS3 transforms for supported devices + @media all and (transform-3d), (-webkit-transform-3d) { + .transition-transform(~'0.6s ease-in-out'); + .backface-visibility(~'hidden'); + .perspective(1000px); + + &.next, + &.active.right { + .translate3d(100%, 0, 0); + left: 0; + } + &.prev, + &.active.left { + .translate3d(-100%, 0, 0); + left: 0; + } + &.next.left, + &.prev.right, + &.active { + .translate3d(0, 0, 0); + left: 0; + } + } } > .active, @@ -106,6 +130,7 @@ .glyphicon-chevron-right { position: absolute; top: 50%; + margin-top: -10px; z-index: 5; display: inline-block; } @@ -123,7 +148,7 @@ .icon-next { width: 20px; height: 20px; - margin-top: -10px; + line-height: 1; font-family: serif; } @@ -171,6 +196,7 @@ // Internet Explorer 8-9 does not support clicks on elements without a set // `background-color`. We cannot use `filter` since that's not viewed as a // background color by the browser. Thus, a hack is needed. + // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Internet_Explorer // // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we // set alpha transparency for the best results possible. diff --git a/bower_components/bootstrap/less/close.less b/bower_components/bootstrap/less/close.less index 9b4e74f..6d5bfe0 100644 --- a/bower_components/bootstrap/less/close.less +++ b/bower_components/bootstrap/less/close.less @@ -23,6 +23,7 @@ // Additional properties for button version // iOS requires the button element instead of an anchor tag. // If you want the anchor version, it requires `href="#"`. + // See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile button& { padding: 0; cursor: pointer; diff --git a/bower_components/bootstrap/less/code.less b/bower_components/bootstrap/less/code.less index baa13df..a08b4d4 100644 --- a/bower_components/bootstrap/less/code.less +++ b/bower_components/bootstrap/less/code.less @@ -32,6 +32,7 @@ kbd { kbd { padding: 0; font-size: 100%; + font-weight: bold; box-shadow: none; } } diff --git a/bower_components/bootstrap/less/component-animations.less b/bower_components/bootstrap/less/component-animations.less index 9400a0d..0bcee91 100644 --- a/bower_components/bootstrap/less/component-animations.less +++ b/bower_components/bootstrap/less/component-animations.less @@ -27,5 +27,7 @@ position: relative; height: 0; overflow: hidden; - .transition(height .35s ease); + .transition-property(~"height, visibility"); + .transition-duration(.35s); + .transition-timing-function(ease); } diff --git a/bower_components/bootstrap/less/dropdowns.less b/bower_components/bootstrap/less/dropdowns.less index 3eb7fc0..f6876c1 100644 --- a/bower_components/bootstrap/less/dropdowns.less +++ b/bower_components/bootstrap/less/dropdowns.less @@ -10,12 +10,14 @@ height: 0; margin-left: 2px; vertical-align: middle; - border-top: @caret-width-base solid; + border-top: @caret-width-base dashed; + border-top: @caret-width-base solid ~"\9"; // IE8 border-right: @caret-width-base solid transparent; border-left: @caret-width-base solid transparent; } // The dropdown wrapper (div) +.dropup, .dropdown { position: relative; } @@ -103,16 +105,15 @@ &:focus { color: @dropdown-link-disabled-color; } -} -// Nuke hover/focus effects -.dropdown-menu > .disabled > a { + + // Nuke hover/focus effects &:hover, &:focus { text-decoration: none; background-color: transparent; background-image: none; // Remove CSS gradient .reset-filter(); - cursor: not-allowed; + cursor: @cursor-disabled; } } @@ -184,14 +185,15 @@ // Reverse the caret .caret { border-top: 0; - border-bottom: @caret-width-base solid; + border-bottom: @caret-width-base dashed; + border-bottom: @caret-width-base solid ~"\9"; // IE8 content: ""; } // Different positioning for bottom up menu .dropdown-menu { top: auto; bottom: 100%; - margin-bottom: 1px; + margin-bottom: 2px; } } @@ -212,4 +214,3 @@ } } } - diff --git a/bower_components/bootstrap/less/forms.less b/bower_components/bootstrap/less/forms.less index 2c5e9bf..b064ede 100644 --- a/bower_components/bootstrap/less/forms.less +++ b/bower_components/bootstrap/less/forms.less @@ -56,7 +56,6 @@ input[type="checkbox"] { line-height: normal; } -// Set the height of file controls to match text inputs input[type="file"] { display: block; } @@ -123,7 +122,7 @@ output { background-color: @input-bg; background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214 border: 1px solid @input-border; - border-radius: @input-border-radius; + border-radius: @input-border-radius; // Note: This has no effect on <select>s in some browsers, due to the limited stylability of <select>s in CSS. .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); .transition(~"border-color ease-in-out .15s, box-shadow ease-in-out .15s"); @@ -141,9 +140,13 @@ output { &[disabled], &[readonly], fieldset[disabled] & { - cursor: not-allowed; background-color: @input-bg-disabled; - opacity: 1; // iOS fix for unreadable disabled content + opacity: 1; // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655 + } + + &[disabled], + fieldset[disabled] & { + cursor: @cursor-disabled; } // Reset height for `textarea`s @@ -168,24 +171,30 @@ input[type="search"] { // Special styles for iOS temporal inputs // // In Mobile Safari, setting `display: block` on temporal inputs causes the -// text within the input to become vertically misaligned. -// As a workaround, we set a pixel line-height that matches the -// given height of the input. Since this fucks up everything else, we have to -// appropriately reset it for Internet Explorer and the size variations. - -input[type="date"], -input[type="time"], -input[type="datetime-local"], -input[type="month"] { - line-height: @input-height-base; - // IE8+ misaligns the text within date inputs, so we reset - line-height: @line-height-base ~"\0"; +// text within the input to become vertically misaligned. As a workaround, we +// set a pixel line-height that matches the given height of the input, but only +// for Safari. See https://bugs.webkit.org/show_bug.cgi?id=139848 +// +// Note that as of 8.3, iOS doesn't support `datetime` or `week`. + +@media screen and (-webkit-min-device-pixel-ratio: 0) { + input[type="date"], + input[type="time"], + input[type="datetime-local"], + input[type="month"] { + &.form-control { + line-height: @input-height-base; + } - &.input-sm { - line-height: @input-height-small; - } - &.input-lg { - line-height: @input-height-large; + &.input-sm, + .input-group-sm & { + line-height: @input-height-small; + } + + &.input-lg, + .input-group-lg & { + line-height: @input-height-large; + } } } @@ -196,7 +205,7 @@ input[type="month"] { // horizontal forms, use the predefined grid classes. .form-group { - margin-bottom: 15px; + margin-bottom: @form-group-margin-bottom; } @@ -208,11 +217,11 @@ input[type="month"] { .checkbox { position: relative; display: block; - min-height: @line-height-computed; // clear the floating input if there is no label text margin-top: 10px; margin-bottom: 10px; label { + min-height: @line-height-computed; // Ensure the input doesn't jump when there is no text padding-left: 20px; margin-bottom: 0; font-weight: normal; @@ -236,6 +245,7 @@ input[type="month"] { // Radios and checkboxes on same line .radio-inline, .checkbox-inline { + position: relative; display: inline-block; padding-left: 20px; margin-bottom: 0; @@ -258,7 +268,7 @@ input[type="checkbox"] { &[disabled], &.disabled, fieldset[disabled] & { - cursor: not-allowed; + cursor: @cursor-disabled; } } // These classes are used directly on <label>s @@ -266,7 +276,7 @@ input[type="checkbox"] { .checkbox-inline { &.disabled, fieldset[disabled] & { - cursor: not-allowed; + cursor: @cursor-disabled; } } // These classes are used on elements with <label> descendants @@ -275,7 +285,7 @@ input[type="checkbox"] { &.disabled, fieldset[disabled] & { label { - cursor: not-allowed; + cursor: @cursor-disabled; } } } @@ -292,6 +302,7 @@ input[type="checkbox"] { padding-bottom: (@padding-base-vertical + 1); // Remove default margin from `p` margin-bottom: 0; + min-height: (@line-height-computed + @font-size-base); &.input-lg, &.input-sm { @@ -305,13 +316,64 @@ input[type="checkbox"] { // // Build on `.form-control` with modifier classes to decrease or increase the // height and font-size of form controls. +// +// The `.form-group-* form-control` variations are sadly duplicated to avoid the +// issue documented in https://github.com/twbs/bootstrap/issues/15074. .input-sm { - .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small); + .input-size(@input-height-small; @padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @input-border-radius-small); +} +.form-group-sm { + .form-control { + height: @input-height-small; + padding: @padding-small-vertical @padding-small-horizontal; + font-size: @font-size-small; + line-height: @line-height-small; + border-radius: @input-border-radius-small; + } + select.form-control { + height: @input-height-small; + line-height: @input-height-small; + } + textarea.form-control, + select[multiple].form-control { + height: auto; + } + .form-control-static { + height: @input-height-small; + min-height: (@line-height-computed + @font-size-small); + padding: (@padding-small-vertical + 1) @padding-small-horizontal; + font-size: @font-size-small; + line-height: @line-height-small; + } } .input-lg { - .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large); + .input-size(@input-height-large; @padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @input-border-radius-large); +} +.form-group-lg { + .form-control { + height: @input-height-large; + padding: @padding-large-vertical @padding-large-horizontal; + font-size: @font-size-large; + line-height: @line-height-large; + border-radius: @input-border-radius-large; + } + select.form-control { + height: @input-height-large; + line-height: @input-height-large; + } + textarea.form-control, + select[multiple].form-control { + height: auto; + } + .form-control-static { + height: @input-height-large; + min-height: (@line-height-computed + @font-size-large); + padding: (@padding-large-vertical + 1) @padding-large-horizontal; + font-size: @font-size-large; + line-height: @line-height-large; + } } @@ -331,7 +393,7 @@ input[type="checkbox"] { // Feedback icon (requires .glyphicon classes) .form-control-feedback { position: absolute; - top: (@line-height-computed + 5); // Height of the `label` and its margin + top: 0; right: 0; z-index: 2; // Ensure icon is above input groups display: block; @@ -339,13 +401,18 @@ input[type="checkbox"] { height: @input-height-base; line-height: @input-height-base; text-align: center; + pointer-events: none; } -.input-lg + .form-control-feedback { +.input-lg + .form-control-feedback, +.input-group-lg + .form-control-feedback, +.form-group-lg .form-control + .form-control-feedback { width: @input-height-large; height: @input-height-large; line-height: @input-height-large; } -.input-sm + .form-control-feedback { +.input-sm + .form-control-feedback, +.input-group-sm + .form-control-feedback, +.form-group-sm .form-control + .form-control-feedback { width: @input-height-small; height: @input-height-small; line-height: @input-height-small; @@ -362,10 +429,15 @@ input[type="checkbox"] { .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-bg); } +// Reposition feedback icon if input has visible label above +.has-feedback label { -// Reposition feedback icon if label is hidden with "screenreader only" state -.has-feedback label.sr-only ~ .form-control-feedback { - top: 0; + & ~ .form-control-feedback { + top: (@line-height-computed + 5); // Height of the `label` and its margin + } + &.sr-only ~ .form-control-feedback { + top: 0; + } } @@ -382,7 +454,6 @@ input[type="checkbox"] { } - // Inline forms // // Make forms appear inline(-block) by adding the `.form-inline` class. Inline @@ -412,6 +483,11 @@ input[type="checkbox"] { vertical-align: middle; } + // Make static controls behave like regular ones + .form-control-static { + display: inline-block; + } + .input-group { display: inline-table; vertical-align: middle; @@ -434,8 +510,7 @@ input[type="checkbox"] { } // Remove default margin on radios/checkboxes that were used for stacking, and - // then undo the floating of radios and checkboxes to match (which also avoids - // a bug in WebKit: https://github.com/twbs/bootstrap/issues/1969). + // then undo the floating of radios and checkboxes to match. .radio, .checkbox { display: inline-block; @@ -453,10 +528,7 @@ input[type="checkbox"] { margin-left: 0; } - // Validation states - // - // Reposition the icon because it's now within a grid column and columns have - // `position: relative;` on them. Also accounts for the grid gutter padding. + // Re-override the feedback icon. .has-feedback .form-control-feedback { top: 0; } @@ -509,8 +581,7 @@ input[type="checkbox"] { // Reposition the icon because it's now within a grid column and columns have // `position: relative;` on them. Also accounts for the grid gutter padding. .has-feedback .form-control-feedback { - top: 0; - right: (@grid-gutter-width / 2); + right: floor((@grid-gutter-width / 2)); } // Form group sizes @@ -521,20 +592,16 @@ input[type="checkbox"] { @media (min-width: @screen-sm-min) { .control-label { padding-top: ((@padding-large-vertical * @line-height-large) + 1); + font-size: @font-size-large; } } - .form-control { - &:extend(.input-lg); - } } .form-group-sm { @media (min-width: @screen-sm-min) { .control-label { padding-top: (@padding-small-vertical + 1); + font-size: @font-size-small; } } - .form-control { - &:extend(.input-sm); - } } } diff --git a/bower_components/bootstrap/less/glyphicons.less b/bower_components/bootstrap/less/glyphicons.less index d3485dc..335d80a 100644 --- a/bower_components/bootstrap/less/glyphicons.less +++ b/bower_components/bootstrap/less/glyphicons.less @@ -12,6 +12,7 @@ font-family: 'Glyphicons Halflings'; src: url('@{icon-font-path}@{icon-font-name}.eot'); src: url('@{icon-font-path}@{icon-font-name}.eot?#iefix') format('embedded-opentype'), + url('@{icon-font-path}@{icon-font-name}.woff2') format('woff2'), url('@{icon-font-path}@{icon-font-name}.woff') format('woff'), url('@{icon-font-path}@{icon-font-name}.ttf') format('truetype'), url('@{icon-font-path}@{icon-font-name}.svg#@{icon-font-svg-id}') format('svg'); @@ -33,7 +34,8 @@ // Individual icons .glyphicon-asterisk { &:before { content: "\2a"; } } .glyphicon-plus { &:before { content: "\2b"; } } -.glyphicon-euro { &:before { content: "\20ac"; } } +.glyphicon-euro, +.glyphicon-eur { &:before { content: "\20ac"; } } .glyphicon-minus { &:before { content: "\2212"; } } .glyphicon-cloud { &:before { content: "\2601"; } } .glyphicon-envelope { &:before { content: "\2709"; } } @@ -231,3 +233,73 @@ .glyphicon-cloud-upload { &:before { content: "\e198"; } } .glyphicon-tree-conifer { &:before { content: "\e199"; } } .glyphicon-tree-deciduous { &:before { content: "\e200"; } } +.glyphicon-cd { &:before { content: "\e201"; } } +.glyphicon-save-file { &:before { content: "\e202"; } } +.glyphicon-open-file { &:before { content: "\e203"; } } +.glyphicon-level-up { &:before { content: "\e204"; } } +.glyphicon-copy { &:before { content: "\e205"; } } +.glyphicon-paste { &:before { content: "\e206"; } } +// The following 2 Glyphicons are omitted for the time being because +// they currently use Unicode codepoints that are outside the +// Basic Multilingual Plane (BMP). Older buggy versions of WebKit can't handle +// non-BMP codepoints in CSS string escapes, and thus can't display these two icons. +// Notably, the bug affects some older versions of the Android Browser. +// More info: https://github.com/twbs/bootstrap/issues/10106 +// .glyphicon-door { &:before { content: "\1f6aa"; } } +// .glyphicon-key { &:before { content: "\1f511"; } } +.glyphicon-alert { &:before { content: "\e209"; } } +.glyphicon-equalizer { &:before { content: "\e210"; } } +.glyphicon-king { &:before { content: "\e211"; } } +.glyphicon-queen { &:before { content: "\e212"; } } +.glyphicon-pawn { &:before { content: "\e213"; } } +.glyphicon-bishop { &:before { content: "\e214"; } } +.glyphicon-knight { &:before { content: "\e215"; } } +.glyphicon-baby-formula { &:before { content: "\e216"; } } +.glyphicon-tent { &:before { content: "\26fa"; } } +.glyphicon-blackboard { &:before { content: "\e218"; } } +.glyphicon-bed { &:before { content: "\e219"; } } +.glyphicon-apple { &:before { content: "\f8ff"; } } +.glyphicon-erase { &:before { content: "\e221"; } } +.glyphicon-hourglass { &:before { content: "\231b"; } } +.glyphicon-lamp { &:before { content: "\e223"; } } +.glyphicon-duplicate { &:before { content: "\e224"; } } +.glyphicon-piggy-bank { &:before { content: "\e225"; } } +.glyphicon-scissors { &:before { content: "\e226"; } } +.glyphicon-bitcoin { &:before { content: "\e227"; } } +.glyphicon-btc { &:before { content: "\e227"; } } +.glyphicon-xbt { &:before { content: "\e227"; } } +.glyphicon-yen { &:before { content: "\00a5"; } } +.glyphicon-jpy { &:before { content: "\00a5"; } } +.glyphicon-ruble { &:before { content: "\20bd"; } } +.glyphicon-rub { &:before { content: "\20bd"; } } +.glyphicon-scale { &:before { content: "\e230"; } } +.glyphicon-ice-lolly { &:before { content: "\e231"; } } +.glyphicon-ice-lolly-tasted { &:before { content: "\e232"; } } +.glyphicon-education { &:before { content: "\e233"; } } +.glyphicon-option-horizontal { &:before { content: "\e234"; } } +.glyphicon-option-vertical { &:before { content: "\e235"; } } +.glyphicon-menu-hamburger { &:before { content: "\e236"; } } +.glyphicon-modal-window { &:before { content: "\e237"; } } +.glyphicon-oil { &:before { content: "\e238"; } } +.glyphicon-grain { &:before { content: "\e239"; } } +.glyphicon-sunglasses { &:before { content: "\e240"; } } +.glyphicon-text-size { &:before { content: "\e241"; } } +.glyphicon-text-color { &:before { content: "\e242"; } } +.glyphicon-text-background { &:before { content: "\e243"; } } +.glyphicon-object-align-top { &:before { content: "\e244"; } } +.glyphicon-object-align-bottom { &:before { content: "\e245"; } } +.glyphicon-object-align-horizontal{ &:before { content: "\e246"; } } +.glyphicon-object-align-left { &:before { content: "\e247"; } } +.glyphicon-object-align-vertical { &:before { content: "\e248"; } } +.glyphicon-object-align-right { &:before { content: "\e249"; } } +.glyphicon-triangle-right { &:before { content: "\e250"; } } +.glyphicon-triangle-left { &:before { content: "\e251"; } } +.glyphicon-triangle-bottom { &:before { content: "\e252"; } } +.glyphicon-triangle-top { &:before { content: "\e253"; } } +.glyphicon-console { &:before { content: "\e254"; } } +.glyphicon-superscript { &:before { content: "\e255"; } } +.glyphicon-subscript { &:before { content: "\e256"; } } +.glyphicon-menu-left { &:before { content: "\e257"; } } +.glyphicon-menu-right { &:before { content: "\e258"; } } +.glyphicon-menu-down { &:before { content: "\e259"; } } +.glyphicon-menu-up { &:before { content: "\e260"; } } diff --git a/bower_components/bootstrap/less/input-groups.less b/bower_components/bootstrap/less/input-groups.less index a8712f2..457ea60 100644 --- a/bower_components/bootstrap/less/input-groups.less +++ b/bower_components/bootstrap/less/input-groups.less @@ -160,6 +160,7 @@ &:last-child { > .btn, > .btn-group { + z-index: 2; margin-left: -1px; } } diff --git a/bower_components/bootstrap/less/jumbotron.less b/bower_components/bootstrap/less/jumbotron.less index 27cd8b8..fa80a38 100644 --- a/bower_components/bootstrap/less/jumbotron.less +++ b/bower_components/bootstrap/less/jumbotron.less @@ -4,7 +4,8 @@ .jumbotron { - padding: @jumbotron-padding; + padding-top: @jumbotron-padding; + padding-bottom: @jumbotron-padding; margin-bottom: @jumbotron-padding; color: @jumbotron-color; background-color: @jumbotron-bg; @@ -13,6 +14,7 @@ .h1 { color: @jumbotron-heading-color; } + p { margin-bottom: (@jumbotron-padding / 2); font-size: @jumbotron-font-size; @@ -23,7 +25,8 @@ border-top-color: darken(@jumbotron-bg, 10%); } - .container & { + .container &, + .container-fluid & { border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container } @@ -35,14 +38,15 @@ padding-top: (@jumbotron-padding * 1.6); padding-bottom: (@jumbotron-padding * 1.6); - .container & { + .container &, + .container-fluid & { padding-left: (@jumbotron-padding * 2); padding-right: (@jumbotron-padding * 2); } h1, .h1 { - font-size: (@font-size-base * 4.5); + font-size: @jumbotron-heading-font-size; } } } diff --git a/bower_components/bootstrap/less/list-group.less b/bower_components/bootstrap/less/list-group.less index 1946bf5..216b912 100644 --- a/bower_components/bootstrap/less/list-group.less +++ b/bower_components/bootstrap/less/list-group.less @@ -35,23 +35,16 @@ margin-bottom: 0; .border-bottom-radius(@list-group-border-radius); } - - // Align badges within list items - > .badge { - float: right; - } - > .badge + .badge { - margin-right: 5px; - } } -// Linked list items +// Interactive list items // -// Use anchor elements instead of `li`s or `div`s to create linked list items. +// Use anchor or button elements instead of `li`s or `div`s to create interactive items. // Includes an extra `.active` modifier class for showing selected items. -a.list-group-item { +a.list-group-item, +button.list-group-item { color: @list-group-link-color; .list-group-item-heading { @@ -67,6 +60,11 @@ a.list-group-item { } } +button.list-group-item { + width: 100%; + text-align: left; +} + .list-group-item { // Disabled state &.disabled, @@ -74,6 +72,7 @@ a.list-group-item { &.disabled:focus { background-color: @list-group-disabled-bg; color: @list-group-disabled-color; + cursor: @cursor-disabled; // Force color to inherit for custom content .list-group-item-heading { diff --git a/bower_components/bootstrap/less/media.less b/bower_components/bootstrap/less/media.less index 5ad22cd..8c835e8 100644 --- a/bower_components/bootstrap/less/media.less +++ b/bower_components/bootstrap/less/media.less @@ -1,54 +1,64 @@ -// Media objects -// Source: http://stubbornella.org/content/?p=497 -// -------------------------------------------------- - +.media { + // Proper spacing between instances of .media + margin-top: 15px; -// Common styles -// ------------------------- + &:first-child { + margin-top: 0; + } +} -// Clear the floats .media, .media-body { - overflow: hidden; zoom: 1; + overflow: hidden; } -// Proper spacing between instances of .media -.media, -.media .media { - margin-top: 15px; -} -.media:first-child { - margin-top: 0; +.media-body { + width: 10000px; } -// For images and videos, set to block .media-object { display: block; + + // Fix collapse in webkit from max-width: 100% and display: table-cell. + &.img-thumbnail { + max-width: none; + } } -// Reset margins on headings for tighter default spacing -.media-heading { - margin: 0 0 5px; +.media-right, +.media > .pull-right { + padding-left: 10px; } +.media-left, +.media > .pull-left { + padding-right: 10px; +} -// Media image alignment -// ------------------------- +.media-left, +.media-right, +.media-body { + display: table-cell; + vertical-align: top; +} -.media { - > .pull-left { - margin-right: 10px; - } - > .pull-right { - margin-left: 10px; - } +.media-middle { + vertical-align: middle; } +.media-bottom { + vertical-align: bottom; +} -// Media list variation -// ------------------------- +// Reset margins on headings for tighter default spacing +.media-heading { + margin-top: 0; + margin-bottom: 5px; +} +// Media list variation +// // Undo default ul/ol styles .media-list { padding-left: 0; diff --git a/bower_components/bootstrap/less/mixins.less b/bower_components/bootstrap/less/mixins.less index af4408f..e6f9fe6 100644 --- a/bower_components/bootstrap/less/mixins.less +++ b/bower_components/bootstrap/less/mixins.less @@ -11,6 +11,7 @@ @import "mixins/responsive-visibility.less"; @import "mixins/size.less"; @import "mixins/tab-focus.less"; +@import "mixins/reset-text.less"; @import "mixins/text-emphasis.less"; @import "mixins/text-overflow.less"; @import "mixins/vendor-prefixes.less"; diff --git a/bower_components/bootstrap/less/mixins/background-variant.less b/bower_components/bootstrap/less/mixins/background-variant.less index 556e490..a85c22b 100644 --- a/bower_components/bootstrap/less/mixins/background-variant.less +++ b/bower_components/bootstrap/less/mixins/background-variant.less @@ -2,7 +2,8 @@ .bg-variant(@color) { background-color: @color; - a&:hover { + a&:hover, + a&:focus { background-color: darken(@color, 10%); } } diff --git a/bower_components/bootstrap/less/mixins/buttons.less b/bower_components/bootstrap/less/mixins/buttons.less index 409f8f2..6875a97 100644 --- a/bower_components/bootstrap/less/mixins/buttons.less +++ b/bower_components/bootstrap/less/mixins/buttons.less @@ -8,14 +8,31 @@ background-color: @background; border-color: @border; - &:hover, &:focus, + &.focus { + color: @color; + background-color: darken(@background, 10%); + border-color: darken(@border, 25%); + } + &:hover { + color: @color; + background-color: darken(@background, 10%); + border-color: darken(@border, 12%); + } &:active, &.active, .open > .dropdown-toggle& { color: @color; background-color: darken(@background, 10%); border-color: darken(@border, 12%); + + &:hover, + &:focus, + &.focus { + color: @color; + background-color: darken(@background, 17%); + border-color: darken(@border, 25%); + } } &:active, &.active, @@ -28,6 +45,7 @@ &, &:hover, &:focus, + &.focus, &:active, &.active { background-color: @background; diff --git a/bower_components/bootstrap/less/mixins/forms.less b/bower_components/bootstrap/less/mixins/forms.less index e36c4a8..6f55ed9 100644 --- a/bower_components/bootstrap/less/mixins/forms.less +++ b/bower_components/bootstrap/less/mixins/forms.less @@ -10,7 +10,11 @@ .radio, .checkbox, .radio-inline, - .checkbox-inline { + .checkbox-inline, + &.radio label, + &.checkbox label, + &.radio-inline label, + &.checkbox-inline label { color: @text-color; } // Set the border and box shadow on specific inputs to match diff --git a/bower_components/bootstrap/less/mixins/grid-framework.less b/bower_components/bootstrap/less/mixins/grid-framework.less index 6317854..8c23eed 100644 --- a/bower_components/bootstrap/less/mixins/grid-framework.less +++ b/bower_components/bootstrap/less/mixins/grid-framework.less @@ -5,7 +5,7 @@ .make-grid-columns() { // Common styles for all sizes of grid columns, widths 1-12 - .col(@index) when (@index = 1) { // initial + .col(@index) { // initial @item: ~".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}"; .col((@index + 1), @item); } @@ -19,15 +19,15 @@ // Prevent columns from collapsing when empty min-height: 1px; // Inner gutter via padding - padding-left: (@grid-gutter-width / 2); - padding-right: (@grid-gutter-width / 2); + padding-left: ceil((@grid-gutter-width / 2)); + padding-right: floor((@grid-gutter-width / 2)); } } .col(1); // kickstart it } .float-grid-columns(@class) { - .col(@index) when (@index = 1) { // initial + .col(@index) { // initial @item: ~".col-@{class}-@{index}"; .col((@index + 1), @item); } diff --git a/bower_components/bootstrap/less/mixins/grid.less b/bower_components/bootstrap/less/mixins/grid.less index cae5eaf..f144c15 100644 --- a/bower_components/bootstrap/less/mixins/grid.less +++ b/bower_components/bootstrap/less/mixins/grid.less @@ -13,8 +13,8 @@ // Creates a wrapper for a series of columns .make-row(@gutter: @grid-gutter-width) { - margin-left: (@gutter / -2); - margin-right: (@gutter / -2); + margin-left: ceil((@gutter / -2)); + margin-right: floor((@gutter / -2)); &:extend(.clearfix all); } diff --git a/bower_components/bootstrap/less/mixins/hide-text.less b/bower_components/bootstrap/less/mixins/hide-text.less index c2315e5..bc70118 100644 --- a/bower_components/bootstrap/less/mixins/hide-text.less +++ b/bower_components/bootstrap/less/mixins/hide-text.less @@ -1,6 +1,6 @@ // CSS image replacement // -// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for +// Heads up! v3 launched with only `.hide-text()`, but per our pattern for // mixins being reused as classes with the same name, this doesn't hold up. As // of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. // diff --git a/bower_components/bootstrap/less/mixins/image.less b/bower_components/bootstrap/less/mixins/image.less index 5d2cccb..f233cb3 100644 --- a/bower_components/bootstrap/less/mixins/image.less +++ b/bower_components/bootstrap/less/mixins/image.less @@ -8,7 +8,6 @@ // Keep images from scaling beyond the width of their parents. .img-responsive(@display: block) { display: @display; - width: 100% \9; // Force IE10 and below to size SVG images correctly max-width: 100%; // Part 1: Set a maximum relative to the parent height: auto; // Part 2: Scale the height according to the width, otherwise you get stretching } diff --git a/bower_components/bootstrap/less/mixins/labels.less b/bower_components/bootstrap/less/mixins/labels.less index 6f9e490..9f7a67e 100644 --- a/bower_components/bootstrap/less/mixins/labels.less +++ b/bower_components/bootstrap/less/mixins/labels.less @@ -2,7 +2,7 @@ .label-variant(@color) { background-color: @color; - + &[href] { &:hover, &:focus { diff --git a/bower_components/bootstrap/less/mixins/list-group.less b/bower_components/bootstrap/less/mixins/list-group.less index 8b5b065..03aa190 100644 --- a/bower_components/bootstrap/less/mixins/list-group.less +++ b/bower_components/bootstrap/less/mixins/list-group.less @@ -5,7 +5,8 @@ color: @color; background-color: @background; - a& { + a&, + button& { color: @color; .list-group-item-heading { diff --git a/bower_components/bootstrap/less/mixins/pagination.less b/bower_components/bootstrap/less/mixins/pagination.less index 7deb505..618804f 100644 --- a/bower_components/bootstrap/less/mixins/pagination.less +++ b/bower_components/bootstrap/less/mixins/pagination.less @@ -1,11 +1,12 @@ // Pagination -.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @border-radius) { +.pagination-size(@padding-vertical; @padding-horizontal; @font-size; @line-height; @border-radius) { > li { > a, > span { padding: @padding-vertical @padding-horizontal; font-size: @font-size; + line-height: @line-height; } &:first-child { > a, diff --git a/bower_components/bootstrap/less/mixins/reset-text.less b/bower_components/bootstrap/less/mixins/reset-text.less new file mode 100644 index 0000000..58dd4d1 --- /dev/null +++ b/bower_components/bootstrap/less/mixins/reset-text.less @@ -0,0 +1,18 @@ +.reset-text() { + font-family: @font-family-base; + // We deliberately do NOT reset font-size. + font-style: normal; + font-weight: normal; + letter-spacing: normal; + line-break: auto; + line-height: @line-height-base; + text-align: left; // Fallback for where `start` is not supported + text-align: start; + text-decoration: none; + text-shadow: none; + text-transform: none; + white-space: normal; + word-break: normal; + word-spacing: normal; + word-wrap: normal; +} diff --git a/bower_components/bootstrap/less/mixins/responsive-visibility.less b/bower_components/bootstrap/less/mixins/responsive-visibility.less index f7951c3..ecf1e97 100644 --- a/bower_components/bootstrap/less/mixins/responsive-visibility.less +++ b/bower_components/bootstrap/less/mixins/responsive-visibility.less @@ -4,7 +4,7 @@ // More easily include all the states for responsive-utilities.less. .responsive-visibility() { display: block !important; - table& { display: table; } + table& { display: table !important; } tr& { display: table-row !important; } th&, td& { display: table-cell !important; } diff --git a/bower_components/bootstrap/less/mixins/text-emphasis.less b/bower_components/bootstrap/less/mixins/text-emphasis.less index 0868ef9..9e8a77a 100644 --- a/bower_components/bootstrap/less/mixins/text-emphasis.less +++ b/bower_components/bootstrap/less/mixins/text-emphasis.less @@ -2,7 +2,8 @@ .text-emphasis-variant(@color) { color: @color; - a&:hover { + a&:hover, + a&:focus { color: darken(@color, 10%); } } diff --git a/bower_components/bootstrap/less/mixins/vendor-prefixes.less b/bower_components/bootstrap/less/mixins/vendor-prefixes.less index e2008c8..afd3331 100644 --- a/bower_components/bootstrap/less/mixins/vendor-prefixes.less +++ b/bower_components/bootstrap/less/mixins/vendor-prefixes.less @@ -99,9 +99,12 @@ // Placeholder text .placeholder(@color: @input-color-placeholder) { - &::-moz-placeholder { color: @color; // Firefox - opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526 - &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+ + // Firefox + &::-moz-placeholder { + color: @color; + opacity: 1; // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526 + } + &:-ms-input-placeholder { color: @color; } // Internet Explorer 10+ &::-webkit-input-placeholder { color: @color; } // Safari and Chrome } diff --git a/bower_components/bootstrap/less/modals.less b/bower_components/bootstrap/less/modals.less index 6da50ba..1de6220 100644 --- a/bower_components/bootstrap/less/modals.less +++ b/bower_components/bootstrap/less/modals.less @@ -30,10 +30,10 @@ // When fading in the modal, animate it to slide down &.fade .modal-dialog { - .translate3d(0, -25%, 0); + .translate(0, -25%); .transition-transform(~"0.3s ease-out"); } - &.in .modal-dialog { .translate3d(0, 0, 0) } + &.in .modal-dialog { .translate(0, 0) } } .modal-open .modal { overflow-x: hidden; diff --git a/bower_components/bootstrap/less/navbar.less b/bower_components/bootstrap/less/navbar.less index 55bfd29..6d751bb 100644 --- a/bower_components/bootstrap/less/navbar.less +++ b/bower_components/bootstrap/less/navbar.less @@ -92,7 +92,7 @@ .navbar-collapse { max-height: @navbar-collapse-max-height; - @media (max-width: @screen-xs-min) and (orientation: landscape) { + @media (max-device-width: @screen-xs-min) and (orientation: landscape) { max-height: 200px; } } @@ -141,7 +141,6 @@ right: 0; left: 0; z-index: @zindex-navbar-fixed; - .translate3d(0, 0, 0); // Undo the rounded corners @media (min-width: @grid-float-breakpoint) { @@ -173,6 +172,10 @@ text-decoration: none; } + > img { + display: block; + } + @media (min-width: @grid-float-breakpoint) { .navbar > .container &, .navbar > .container-fluid & { @@ -271,26 +274,10 @@ padding-bottom: @navbar-padding-vertical; } } - - &.navbar-right:last-child { - margin-right: -@navbar-padding-horizontal; - } } } -// Component alignment -// -// Repurpose the pull utilities as their own navbar utilities to avoid specificity -// issues with parents and chaining. Only do this when the navbar is uncollapsed -// though so that navbar contents properly stack and align in mobile. - -@media (min-width: @grid-float-breakpoint) { - .navbar-left { .pull-left(); } - .navbar-right { .pull-right(); } -} - - // Navbar form // // Extension of the `.form-inline` with some extra flavor for optimum display in @@ -311,6 +298,10 @@ .form-group { @media (max-width: @grid-float-breakpoint-max) { margin-bottom: 5px; + + &:last-child { + margin-bottom: 0; + } } } @@ -326,11 +317,6 @@ padding-top: 0; padding-bottom: 0; .box-shadow(none); - - // Outdent the form if last child to line up with content down the page - &.navbar-right:last-child { - margin-right: -@navbar-padding-horizontal; - } } } @@ -344,6 +330,8 @@ } // Menu position and menu caret support for dropups via extra dropup class .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { + margin-bottom: 0; + .border-top-radius(@navbar-border-radius); .border-bottom-radius(0); } @@ -375,14 +363,31 @@ float: left; margin-left: @navbar-padding-horizontal; margin-right: @navbar-padding-horizontal; + } +} + - // Outdent the form if last child to line up with content down the page - &.navbar-right:last-child { +// Component alignment +// +// Repurpose the pull utilities as their own navbar utilities to avoid specificity +// issues with parents and chaining. Only do this when the navbar is uncollapsed +// though so that navbar contents properly stack and align in mobile. +// +// Declared after the navbar components to ensure more specificity on the margins. + +@media (min-width: @grid-float-breakpoint) { + .navbar-left { .pull-left(); } + .navbar-right { + .pull-right(); + margin-right: -@navbar-padding-horizontal; + + ~ .navbar-right { margin-right: 0; } } } + // Alternate navbars // -------------------------------------------------- diff --git a/bower_components/bootstrap/less/navs.less b/bower_components/bootstrap/less/navs.less index 98a6430..a3d11b1 100644 --- a/bower_components/bootstrap/less/navs.less +++ b/bower_components/bootstrap/less/navs.less @@ -36,7 +36,7 @@ color: @nav-disabled-link-hover-color; text-decoration: none; background-color: transparent; - cursor: not-allowed; + cursor: @cursor-disabled; } } } diff --git a/bower_components/bootstrap/less/normalize.less b/bower_components/bootstrap/less/normalize.less index ce04b6a..9dddf73 100644 --- a/bower_components/bootstrap/less/normalize.less +++ b/bower_components/bootstrap/less/normalize.less @@ -1,9 +1,9 @@ -/*! normalize.css v3.0.1 | MIT License | git.io/normalize */ +/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ // // 1. Set default font family to sans-serif. -// 2. Prevent iOS text size adjust after orientation change, without disabling -// user zoom. +// 2. Prevent iOS and IE text size adjust after device orientation change, +// without disabling user zoom. // html { @@ -25,7 +25,8 @@ body { // // Correct `block` display not defined for any HTML5 element in IE 8/9. -// Correct `block` display not defined for `details` or `summary` in IE 10/11 and Firefox. +// Correct `block` display not defined for `details` or `summary` in IE 10/11 +// and Firefox. // Correct `block` display not defined for `main` in IE 11. // @@ -38,6 +39,7 @@ footer, header, hgroup, main, +menu, nav, section, summary { @@ -69,7 +71,7 @@ audio:not([controls]) { // // Address `[hidden]` styling not present in IE 8/9/10. -// Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. +// Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22. // [hidden], @@ -85,11 +87,12 @@ template { // a { - background: transparent; + background-color: transparent; } // -// Improve readability when focused and also mouse hovered in all browsers. +// Improve readability of focused elements when they are also in an +// active/hover state. // a:active, @@ -207,7 +210,6 @@ figure { // hr { - -moz-box-sizing: content-box; box-sizing: content-box; height: 0; } @@ -348,15 +350,12 @@ input[type="number"]::-webkit-outer-spin-button { // // 1. Address `appearance` set to `searchfield` in Safari and Chrome. -// 2. Address `box-sizing` set to `border-box` in Safari and Chrome -// (include `-moz` to future-proof). +// 2. Address `box-sizing` set to `border-box` in Safari and Chrome. // input[type="search"] { -webkit-appearance: textfield; // 1 - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; // 2 - box-sizing: content-box; + box-sizing: content-box; //2 } // diff --git a/bower_components/bootstrap/less/pager.less b/bower_components/bootstrap/less/pager.less index 59103f4..41abaaa 100644 --- a/bower_components/bootstrap/less/pager.less +++ b/bower_components/bootstrap/less/pager.less @@ -48,8 +48,7 @@ > span { color: @pager-disabled-color; background-color: @pager-bg; - cursor: not-allowed; + cursor: @cursor-disabled; } } - } diff --git a/bower_components/bootstrap/less/pagination.less b/bower_components/bootstrap/less/pagination.less index b2856ae..31a23bf 100644 --- a/bower_components/bootstrap/less/pagination.less +++ b/bower_components/bootstrap/less/pagination.less @@ -40,6 +40,7 @@ > li > span { &:hover, &:focus { + z-index: 3; color: @pagination-hover-color; background-color: @pagination-hover-bg; border-color: @pagination-hover-border; @@ -69,7 +70,7 @@ color: @pagination-disabled-color; background-color: @pagination-disabled-bg; border-color: @pagination-disabled-border; - cursor: not-allowed; + cursor: @cursor-disabled; } } } @@ -79,10 +80,10 @@ // Large .pagination-lg { - .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @border-radius-large); + .pagination-size(@padding-large-vertical; @padding-large-horizontal; @font-size-large; @line-height-large; @border-radius-large); } // Small .pagination-sm { - .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @border-radius-small); + .pagination-size(@padding-small-vertical; @padding-small-horizontal; @font-size-small; @line-height-small; @border-radius-small); } diff --git a/bower_components/bootstrap/less/panels.less b/bower_components/bootstrap/less/panels.less index 2dc2131..425eb5e 100644 --- a/bower_components/bootstrap/less/panels.less +++ b/bower_components/bootstrap/less/panels.less @@ -36,7 +36,11 @@ font-size: ceil((@font-size-base * 1.125)); color: inherit; - > a { + > a, + > small, + > .small, + > small > a, + > .small > a { color: inherit; } } @@ -56,7 +60,8 @@ // any kind of custom content between the two. .panel { - > .list-group { + > .list-group, + > .panel-collapse > .list-group { margin-bottom: 0; .list-group-item { @@ -71,6 +76,7 @@ .border-top-radius((@panel-border-radius - 1)); } } + // Add border bottom radius for last one &:last-child { .list-group-item:last-child { @@ -79,6 +85,11 @@ } } } + > .panel-heading + .panel-collapse > .list-group { + .list-group-item:first-child { + .border-top-radius(0); + } + } } // Collapse space between when there's no additional content. .panel-heading + .list-group { @@ -100,6 +111,11 @@ > .table-responsive > .table, > .panel-collapse > .table { margin-bottom: 0; + + caption { + padding-left: @panel-body-padding; + padding-right: @panel-body-padding; + } } // Add border top radius for first one > .table:first-child, @@ -109,6 +125,9 @@ > thead:first-child, > tbody:first-child { > tr:first-child { + border-top-left-radius: (@panel-border-radius - 1); + border-top-right-radius: (@panel-border-radius - 1); + td:first-child, th:first-child { border-top-left-radius: (@panel-border-radius - 1); @@ -128,6 +147,9 @@ > tbody:last-child, > tfoot:last-child { > tr:last-child { + border-bottom-left-radius: (@panel-border-radius - 1); + border-bottom-right-radius: (@panel-border-radius - 1); + td:first-child, th:first-child { border-bottom-left-radius: (@panel-border-radius - 1); @@ -140,7 +162,9 @@ } } > .panel-body + .table, - > .panel-body + .table-responsive { + > .panel-body + .table-responsive, + > .table + .panel-body, + > .table-responsive + .panel-body { border-top: 1px solid @table-border-color; } > .table > tbody:first-child > tr:first-child th, @@ -202,6 +226,7 @@ .panel { margin-bottom: 0; border-radius: @panel-border-radius; + + .panel { margin-top: 5px; } @@ -209,10 +234,13 @@ .panel-heading { border-bottom: 0; - + .panel-collapse > .panel-body { + + + .panel-collapse > .panel-body, + + .panel-collapse > .list-group { border-top: 1px solid @panel-inner-border; } } + .panel-footer { border-top: 0; + .panel-collapse .panel-body { diff --git a/bower_components/bootstrap/less/popovers.less b/bower_components/bootstrap/less/popovers.less index bf6af40..3a62a64 100644 --- a/bower_components/bootstrap/less/popovers.less +++ b/bower_components/bootstrap/less/popovers.less @@ -11,7 +11,11 @@ display: none; max-width: @popover-max-width; padding: 1px; - text-align: left; // Reset given new insertion method + // Our parent element can be arbitrary since popovers are by default inserted as a sibling of their target element. + // So reset our font and text properties to avoid inheriting weird values. + .reset-text(); + font-size: @font-size-base; + background-color: @popover-bg; background-clip: padding-box; border: 1px solid @popover-fallback-border-color; @@ -19,9 +23,6 @@ border-radius: @border-radius-large; .box-shadow(0 5px 10px rgba(0,0,0,.2)); - // Overrides for proper insertion - white-space: normal; - // Offset the popover to account for the popover arrow &.top { margin-top: -@popover-arrow-width; } &.right { margin-left: @popover-arrow-width; } @@ -33,8 +34,6 @@ margin: 0; // reset heading margin padding: 8px 14px; font-size: @font-size-base; - font-weight: normal; - line-height: 18px; background-color: @popover-title-bg; border-bottom: 1px solid darken(@popover-title-bg, 5%); border-radius: (@border-radius-large - 1) (@border-radius-large - 1) 0 0; @@ -129,5 +128,4 @@ bottom: -@popover-arrow-width; } } - } diff --git a/bower_components/bootstrap/less/print.less b/bower_components/bootstrap/less/print.less index 3655d03..66e54ab 100644 --- a/bower_components/bootstrap/less/print.less +++ b/bower_components/bootstrap/less/print.less @@ -1,101 +1,101 @@ -// -// Basic print styles -// -------------------------------------------------- -// Source: https://github.com/h5bp/html5-boilerplate/blob/master/css/main.css +/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ + +// ========================================================================== +// Print styles. +// Inlined to avoid the additional HTTP request: h5bp.com/r +// ========================================================================== @media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; // Black prints faster: h5bp.com/s + box-shadow: none !important; + text-shadow: none !important; + } + + a, + a:visited { + text-decoration: underline; + } + + a[href]:after { + content: " (" attr(href) ")"; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + // Don't show links that are fragment identifiers, + // or use the `javascript:` pseudo protocol + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + + thead { + display: table-header-group; // h5bp.com/t + } + + tr, + img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + + h2, + h3 { + page-break-after: avoid; + } + + // Bootstrap specific changes start - * { - text-shadow: none !important; - color: #000 !important; // Black prints faster: h5bp.com/s - background: transparent !important; - box-shadow: none !important; - } - - a, - a:visited { - text-decoration: underline; - } - - a[href]:after { - content: " (" attr(href) ")"; - } - - abbr[title]:after { - content: " (" attr(title) ")"; - } - - // Don't show links for images, or javascript/internal links - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - - pre, - blockquote { - border: 1px solid #999; - page-break-inside: avoid; - } - - thead { - display: table-header-group; // h5bp.com/t - } - - tr, - img { - page-break-inside: avoid; - } - - img { - max-width: 100% !important; - } - - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - - h2, - h3 { - page-break-after: avoid; - } - - // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245 - // Once fixed, we can just straight up remove this. - select { - background: #fff !important; - } - - // Bootstrap components - .navbar { - display: none; - } - .table { - td, - th { - background-color: #fff !important; - } - } - .btn, - .dropup > .btn { - > .caret { - border-top-color: #000 !important; - } - } - .label { - border: 1px solid #000; - } - - .table { - border-collapse: collapse !important; - } - .table-bordered { - th, - td { - border: 1px solid #ddd !important; - } - } + // Bootstrap components + .navbar { + display: none; + } + .btn, + .dropup > .btn { + > .caret { + border-top-color: #000 !important; + } + } + .label { + border: 1px solid #000; + } + + .table { + border-collapse: collapse !important; + + td, + th { + background-color: #fff !important; + } + } + .table-bordered { + th, + td { + border: 1px solid #ddd !important; + } + } + // Bootstrap specific changes end } diff --git a/bower_components/bootstrap/less/progress-bars.less b/bower_components/bootstrap/less/progress-bars.less index 3ac52a2..8868a1f 100644 --- a/bower_components/bootstrap/less/progress-bars.less +++ b/bower_components/bootstrap/less/progress-bars.less @@ -19,7 +19,6 @@ } - // Bar itself // ------------------------- @@ -29,7 +28,7 @@ height: @line-height-computed; margin-bottom: @line-height-computed; background-color: @progress-bg; - border-radius: @border-radius-base; + border-radius: @progress-border-radius; .box-shadow(inset 0 1px 2px rgba(0,0,0,.1)); } @@ -67,23 +66,6 @@ .animation(progress-bar-stripes 2s linear infinite); } -// Account for lower percentages -.progress-bar { - &[aria-valuenow="1"], - &[aria-valuenow="2"] { - min-width: 30px; - } - - &[aria-valuenow="0"] { - color: @gray-light; - min-width: 30px; - background-color: transparent; - background-image: none; - box-shadow: none; - } -} - - // Variations // ------------------------- diff --git a/bower_components/bootstrap/less/responsive-embed.less b/bower_components/bootstrap/less/responsive-embed.less index a884d49..080a511 100644 --- a/bower_components/bootstrap/less/responsive-embed.less +++ b/bower_components/bootstrap/less/responsive-embed.less @@ -12,7 +12,8 @@ .embed-responsive-item, iframe, embed, - object { + object, + video { position: absolute; top: 0; left: 0; @@ -21,14 +22,14 @@ width: 100%; border: 0; } +} - // Modifier class for 16:9 aspect ratio - &.embed-responsive-16by9 { - padding-bottom: 56.25%; - } +// Modifier class for 16:9 aspect ratio +.embed-responsive-16by9 { + padding-bottom: 56.25%; +} - // Modifier class for 4:3 aspect ratio - &.embed-responsive-4by3 { - padding-bottom: 75%; - } +// Modifier class for 4:3 aspect ratio +.embed-responsive-4by3 { + padding-bottom: 75%; } diff --git a/bower_components/bootstrap/less/scaffolding.less b/bower_components/bootstrap/less/scaffolding.less index c1e270f..1929bfc 100644 --- a/bower_components/bootstrap/less/scaffolding.less +++ b/bower_components/bootstrap/less/scaffolding.less @@ -52,7 +52,7 @@ a { &:hover, &:focus { color: @link-hover-color; - text-decoration: underline; + text-decoration: @link-hover-decoration; } &:focus { @@ -148,3 +148,14 @@ hr { clip: auto; } } + + +// iOS "clickable elements" fix for role="button" +// +// Fixes "clickability" issue (and more generally, the firing of events such as focus as well) +// for traditionally non-focusable elements with role="button" +// see https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile + +[role="button"] { + cursor: pointer; +} diff --git a/bower_components/bootstrap/less/tables.less b/bower_components/bootstrap/less/tables.less index 2e1ef33..2242c03 100644 --- a/bower_components/bootstrap/less/tables.less +++ b/bower_components/bootstrap/less/tables.less @@ -6,6 +6,12 @@ table { background-color: @table-bg; } +caption { + padding-top: @table-cell-padding; + padding-bottom: @table-cell-padding; + color: @text-muted; + text-align: left; +} th { text-align: left; } @@ -105,11 +111,8 @@ th { // Default zebra-stripe styles (alternating gray and transparent backgrounds) .table-striped { - > tbody > tr:nth-child(odd) { - > td, - > th { - background-color: @table-bg-accent; - } + > tbody > tr:nth-of-type(odd) { + background-color: @table-bg-accent; } } @@ -120,10 +123,7 @@ th { .table-hover { > tbody > tr:hover { - > td, - > th { - background-color: @table-bg-hover; - } + background-color: @table-bg-hover; } } @@ -133,7 +133,7 @@ th { // Reset default table behavior table col[class*="col-"] { - position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623) + position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623) float: none; display: table-column; } @@ -141,7 +141,7 @@ table { td, th { &[class*="col-"] { - position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623) + position: static; // Prevent border hiding in Firefox and IE9-11 (see https://github.com/twbs/bootstrap/issues/11623) float: none; display: table-cell; } @@ -169,14 +169,15 @@ table { // will display normally. .table-responsive { + overflow-x: auto; + min-height: 0.01%; // Workaround for IE9 bug (see https://github.com/twbs/bootstrap/issues/14837) + @media screen and (max-width: @screen-xs-max) { width: 100%; margin-bottom: (@line-height-computed * 0.75); overflow-y: hidden; - overflow-x: auto; -ms-overflow-style: -ms-autohiding-scrollbar; border: 1px solid @table-border-color; - -webkit-overflow-scrolling: touch; // Tighten up spacing > .table { diff --git a/bower_components/bootstrap/less/theme.less b/bower_components/bootstrap/less/theme.less index b089424..8371872 100644 --- a/bower_components/bootstrap/less/theme.less +++ b/bower_components/bootstrap/less/theme.less @@ -1,3 +1,8 @@ +/*! + * Bootstrap v3.3.5 (http://getbootstrap.com) + * Copyright 2011-2015 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ // // Load core variables and mixins @@ -7,7 +12,6 @@ @import "mixins.less"; - // // Buttons // -------------------------------------------------- @@ -28,12 +32,22 @@ &.active { .box-shadow(inset 0 3px 5px rgba(0,0,0,.125)); } + + &.disabled, + &[disabled], + fieldset[disabled] & { + .box-shadow(none); + } + + .badge { + text-shadow: none; + } } // Mixin for generating new styles .btn-styles(@btn-color: #555) { #gradient > .vertical(@start-color: @btn-color; @end-color: darken(@btn-color, 12%)); - .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners + .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners; see https://github.com/twbs/bootstrap/issues/10620 background-repeat: repeat-x; border-color: darken(@btn-color, 14%); @@ -49,10 +63,18 @@ border-color: darken(@btn-color, 14%); } - &:disabled, - &[disabled] { - background-color: darken(@btn-color, 12%); - background-image: none; + &.disabled, + &[disabled], + fieldset[disabled] & { + &, + &:hover, + &:focus, + &.focus, + &:active, + &.active { + background-color: darken(@btn-color, 12%); + background-image: none; + } } } @@ -74,7 +96,6 @@ .btn-danger { .btn-styles(@btn-danger-bg); } - // // Images // -------------------------------------------------- @@ -85,7 +106,6 @@ } - // // Dropdowns // -------------------------------------------------- @@ -103,7 +123,6 @@ } - // // Navbar // -------------------------------------------------- @@ -116,8 +135,9 @@ @shadow: inset 0 1px 0 rgba(255,255,255,.15), 0 1px 5px rgba(0,0,0,.075); .box-shadow(@shadow); + .navbar-nav > .open > a, .navbar-nav > .active > a { - #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%)); + #gradient > .vertical(@start-color: darken(@navbar-default-link-active-bg, 5%); @end-color: darken(@navbar-default-link-active-bg, 2%)); .box-shadow(inset 0 3px 9px rgba(0,0,0,.075)); } } @@ -129,10 +149,11 @@ // Inverted navbar .navbar-inverse { #gradient > .vertical(@start-color: lighten(@navbar-inverse-bg, 10%); @end-color: @navbar-inverse-bg); - .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered - + .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered; see https://github.com/twbs/bootstrap/issues/10257 + border-radius: @navbar-border-radius; + .navbar-nav > .open > a, .navbar-nav > .active > a { - #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%)); + #gradient > .vertical(@start-color: @navbar-inverse-link-active-bg; @end-color: lighten(@navbar-inverse-link-active-bg, 2.5%)); .box-shadow(inset 0 3px 9px rgba(0,0,0,.25)); } @@ -149,6 +170,17 @@ border-radius: 0; } +// Fix active state of dropdown items in collapsed mode +@media (max-width: @grid-float-breakpoint-max) { + .navbar .navbar-nav .open .dropdown-menu > .active > a { + &, + &:hover, + &:focus { + color: #fff; + #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%)); + } + } +} // @@ -175,7 +207,6 @@ .alert-danger { .alert-styles(@alert-danger-bg); } - // // Progress bars // -------------------------------------------------- @@ -218,8 +249,11 @@ text-shadow: 0 -1px 0 darken(@list-group-active-bg, 10%); #gradient > .vertical(@start-color: @list-group-active-bg; @end-color: darken(@list-group-active-bg, 7.5%)); border-color: darken(@list-group-active-border, 7.5%); -} + .badge { + text-shadow: none; + } +} // @@ -245,7 +279,6 @@ .panel-danger > .panel-heading { .panel-heading-styles(@panel-danger-heading-bg); } - // // Wells // -------------------------------------------------- diff --git a/bower_components/bootstrap/less/thumbnails.less b/bower_components/bootstrap/less/thumbnails.less index c428920..0713e67 100644 --- a/bower_components/bootstrap/less/thumbnails.less +++ b/bower_components/bootstrap/less/thumbnails.less @@ -12,7 +12,7 @@ background-color: @thumbnail-bg; border: 1px solid @thumbnail-border; border-radius: @thumbnail-border-radius; - .transition(all .2s ease-in-out); + .transition(border .2s ease-in-out); > img, a > img { diff --git a/bower_components/bootstrap/less/tooltip.less b/bower_components/bootstrap/less/tooltip.less index bd62699..b48d63e 100644 --- a/bower_components/bootstrap/less/tooltip.less +++ b/bower_components/bootstrap/less/tooltip.less @@ -8,9 +8,11 @@ position: absolute; z-index: @zindex-tooltip; display: block; - visibility: visible; + // Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element. + // So reset our font and text properties to avoid inheriting weird values. + .reset-text(); font-size: @font-size-small; - line-height: 1.4; + .opacity(0); &.in { .opacity(@tooltip-opacity); } @@ -26,7 +28,6 @@ padding: 3px 8px; color: @tooltip-color; text-align: center; - text-decoration: none; background-color: @tooltip-bg; border-radius: @border-radius-base; } @@ -39,6 +40,7 @@ border-color: transparent; border-style: solid; } +// Note: Deprecated .top-left, .top-right, .bottom-left, and .bottom-right as of v3.3.1 .tooltip { &.top .tooltip-arrow { bottom: 0; @@ -49,13 +51,15 @@ } &.top-left .tooltip-arrow { bottom: 0; - left: @tooltip-arrow-width; + right: @tooltip-arrow-width; + margin-bottom: -@tooltip-arrow-width; border-width: @tooltip-arrow-width @tooltip-arrow-width 0; border-top-color: @tooltip-arrow-color; } &.top-right .tooltip-arrow { bottom: 0; - right: @tooltip-arrow-width; + left: @tooltip-arrow-width; + margin-bottom: -@tooltip-arrow-width; border-width: @tooltip-arrow-width @tooltip-arrow-width 0; border-top-color: @tooltip-arrow-color; } @@ -82,13 +86,15 @@ } &.bottom-left .tooltip-arrow { top: 0; - left: @tooltip-arrow-width; + right: @tooltip-arrow-width; + margin-top: -@tooltip-arrow-width; border-width: 0 @tooltip-arrow-width @tooltip-arrow-width; border-bottom-color: @tooltip-arrow-color; } &.bottom-right .tooltip-arrow { top: 0; - right: @tooltip-arrow-width; + left: @tooltip-arrow-width; + margin-top: -@tooltip-arrow-width; border-width: 0 @tooltip-arrow-width @tooltip-arrow-width; border-bottom-color: @tooltip-arrow-color; } diff --git a/bower_components/bootstrap/less/type.less b/bower_components/bootstrap/less/type.less index 9b1e48b..68ba601 100644 --- a/bower_components/bootstrap/less/type.less +++ b/bower_components/bootstrap/less/type.less @@ -80,11 +80,6 @@ small, font-size: floor((100% * @font-size-small / @font-size-base)); } -// Undo browser default styling -cite { - font-style: normal; -} - mark, .mark { background-color: @state-warning-bg; @@ -243,7 +238,7 @@ abbr[data-original-title] { } .initialism { font-size: 90%; - text-transform: uppercase; + .text-uppercase(); } // Blockquotes @@ -299,12 +294,6 @@ blockquote.pull-right { } } -// Quotes -blockquote:before, -blockquote:after { - content: ""; -} - // Addresses address { margin-bottom: @line-height-computed; diff --git a/bower_components/bootstrap/less/utilities.less b/bower_components/bootstrap/less/utilities.less index c0becab..7a8ca27 100644 --- a/bower_components/bootstrap/less/utilities.less +++ b/bower_components/bootstrap/less/utilities.less @@ -44,7 +44,6 @@ .hidden { display: none !important; - visibility: hidden !important; } @@ -53,5 +52,4 @@ .affix { position: fixed; - .translate3d(0, 0, 0); } diff --git a/bower_components/bootstrap/less/variables.less b/bower_components/bootstrap/less/variables.less index 582f0f8..c1861a8 100644 --- a/bower_components/bootstrap/less/variables.less +++ b/bower_components/bootstrap/less/variables.less @@ -7,13 +7,14 @@ // //## Gray and brand colors for use across Bootstrap. -@gray-darker: lighten(#000, 13.5%); // #222 -@gray-dark: lighten(#000, 20%); // #333 -@gray: lighten(#000, 33.5%); // #555 -@gray-light: lighten(#000, 46.7%); // #777 -@gray-lighter: lighten(#000, 93.5%); // #eee - -@brand-primary: #428bca; +@gray-base: #000; +@gray-darker: lighten(@gray-base, 13.5%); // #222 +@gray-dark: lighten(@gray-base, 20%); // #333 +@gray: lighten(@gray-base, 33.5%); // #555 +@gray-light: lighten(@gray-base, 46.7%); // #777 +@gray-lighter: lighten(@gray-base, 93.5%); // #eee + +@brand-primary: darken(#428bca, 6.5%); // #337ab7 @brand-success: #5cb85c; @brand-info: #5bc0de; @brand-warning: #f0ad4e; @@ -33,6 +34,8 @@ @link-color: @brand-primary; //** Link hover color set via `darken()` function. @link-hover-color: darken(@link-color, 15%); +//** Link hover decoration. +@link-hover-decoration: underline; //== Typography @@ -96,7 +99,7 @@ @padding-xs-vertical: 1px; @padding-xs-horizontal: 5px; -@line-height-large: 1.33; +@line-height-large: 1.3333333; // extra decimals for Win 8.1 Chrome @line-height-small: 1.5; @border-radius-base: 4px; @@ -167,6 +170,11 @@ @btn-link-disabled-color: @gray-light; +// Allows for customizing button radius independently from global border radius +@btn-border-radius-base: @border-radius-base; +@btn-border-radius-large: @border-radius-large; +@btn-border-radius-small: @border-radius-small; + //== Forms // @@ -181,13 +189,21 @@ @input-color: @gray; //** `<input>` border color @input-border: #ccc; -//** `<input>` border radius + +// TODO: Rename `@input-border-radius` to `@input-border-radius-base` in v4 +//** Default `.form-control` border radius +// This has no effect on `<select>`s in some browsers, due to the limited stylability of `<select>`s in CSS. @input-border-radius: @border-radius-base; +//** Large `.form-control` border radius +@input-border-radius-large: @border-radius-large; +//** Small `.form-control` border radius +@input-border-radius-small: @border-radius-small; + //** Border color for inputs on focus @input-border-focus: #66afe9; //** Placeholder text color -@input-color-placeholder: @gray-light; +@input-color-placeholder: #999; //** Default `.form-control` height @input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2); @@ -196,6 +212,9 @@ //** Small `.form-control` height @input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2); +//** `.form-group` margin +@form-group-margin-bottom: 15px; + @legend-color: @gray-dark; @legend-border-color: #e5e5e5; @@ -204,6 +223,9 @@ //** Border color for textual input addons @input-group-addon-border-color: @input-border; +//** Disabled cursor for form controls and buttons. +@cursor-disabled: not-allowed; + //== Dropdowns // @@ -315,17 +337,17 @@ //## Define the maximum width of `.container` for different screen sizes. // Small screen / tablet -@container-tablet: ((720px + @grid-gutter-width)); +@container-tablet: (720px + @grid-gutter-width); //** For `@screen-sm-min` and up. @container-sm: @container-tablet; // Medium screen / desktop -@container-desktop: ((940px + @grid-gutter-width)); +@container-desktop: (940px + @grid-gutter-width); //** For `@screen-md-min` and up. @container-md: @container-desktop; // Large screen / wide desktop -@container-large-desktop: ((1140px + @grid-gutter-width)); +@container-large-desktop: (1140px + @grid-gutter-width); //** For `@screen-lg-min` and up. @container-lg: @container-large-desktop; @@ -366,14 +388,14 @@ @navbar-default-toggle-border-color: #ddd; -// Inverted navbar +//=== Inverted navbar // Reset inverted navbar basics -@navbar-inverse-color: @gray-light; +@navbar-inverse-color: lighten(@gray-light, 15%); @navbar-inverse-bg: #222; @navbar-inverse-border: darken(@navbar-inverse-bg, 10%); // Inverted navbar links -@navbar-inverse-link-color: @gray-light; +@navbar-inverse-link-color: lighten(@gray-light, 15%); @navbar-inverse-link-hover-color: #fff; @navbar-inverse-link-hover-bg: transparent; @navbar-inverse-link-active-color: @navbar-inverse-link-hover-color; @@ -403,8 +425,6 @@ @nav-disabled-link-color: @gray-light; @nav-disabled-link-hover-color: @gray-light; -@nav-open-link-hover-color: #fff; - //== Tabs @nav-tabs-border-color: #ddd; @@ -469,6 +489,7 @@ @jumbotron-bg: @gray-lighter; @jumbotron-heading-color: inherit; @jumbotron-font-size: ceil((@font-size-base * 1.5)); +@jumbotron-heading-font-size: ceil((@font-size-base * 4.5)); //== Form states and alerts @@ -529,7 +550,7 @@ //** Popover arrow width @popover-arrow-width: 10px; //** Popover arrow color -@popover-arrow-color: #fff; +@popover-arrow-color: @popover-bg; //** Popover outer arrow width @popover-arrow-outer-width: (@popover-arrow-width + 1); @@ -628,6 +649,8 @@ @progress-bg: #f5f5f5; //** Progress bar text color @progress-bar-color: #fff; +//** Variable for setting rounded corners on progress bar. +@progress-border-radius: @border-radius-base; //** Default progress bar color @progress-bar-bg: @brand-primary; @@ -842,5 +865,3 @@ @dl-horizontal-offset: @component-offset-horizontal; //** Horizontal line color. @hr-border: @gray-lighter; - - diff --git a/bower_components/bootstrap/package.js b/bower_components/bootstrap/package.js new file mode 100644 index 0000000..81d42a6 --- /dev/null +++ b/bower_components/bootstrap/package.js @@ -0,0 +1,25 @@ +// package metadata file for Meteor.js + +/* jshint strict:false */ +/* global Package:true */ + +Package.describe({ + name: 'twbs:bootstrap', // http://atmospherejs.com/twbs/bootstrap + summary: 'The most popular front-end framework for developing responsive, mobile first projects on the web.', + version: '3.3.5', + git: 'https://github.com/twbs/bootstrap.git' +}); + +Package.onUse(function (api) { + api.versionsFrom('METEOR@1.0'); + api.use('jquery', 'client'); + api.addFiles([ + 'dist/fonts/glyphicons-halflings-regular.eot', + 'dist/fonts/glyphicons-halflings-regular.svg', + 'dist/fonts/glyphicons-halflings-regular.ttf', + 'dist/fonts/glyphicons-halflings-regular.woff', + 'dist/fonts/glyphicons-halflings-regular.woff2', + 'dist/css/bootstrap.css', + 'dist/js/bootstrap.js' + ], 'client'); +}); diff --git a/bower_components/bootstrap/package.json b/bower_components/bootstrap/package.json index 3243fa8..380472a 100644 --- a/bower_components/bootstrap/package.json +++ b/bower_components/bootstrap/package.json @@ -1,7 +1,7 @@ { "name": "bootstrap", "description": "The most popular front-end framework for developing responsive, mobile first projects on the web.", - "version": "3.2.0", + "version": "3.3.5", "keywords": [ "css", "less", @@ -18,6 +18,7 @@ }, "style": "dist/css/bootstrap.css", "less": "less/bootstrap.less", + "main": "./dist/js/npm", "repository": { "type": "git", "url": "https://github.com/twbs/bootstrap.git" @@ -25,57 +26,62 @@ "bugs": { "url": "https://github.com/twbs/bootstrap/issues" }, - "license": { - "type": "MIT", - "url": "https://github.com/twbs/bootstrap/blob/master/LICENSE" - }, + "license": "MIT", "devDependencies": { "btoa": "~1.1.2", - "glob": "~4.0.2", + "glob": "~5.0.5", "grunt": "~0.4.5", - "grunt-autoprefixer": "~0.7.6", - "grunt-banner": "~0.2.3", - "grunt-contrib-clean": "~0.5.0", - "grunt-contrib-concat": "~0.4.0", - "grunt-contrib-connect": "~0.8.0", - "grunt-contrib-copy": "~0.5.0", - "grunt-contrib-csslint": "~0.2.0", - "grunt-contrib-cssmin": "~0.10.0", - "grunt-contrib-jade": "~0.12.0", - "grunt-contrib-jshint": "~0.10.0", - "grunt-contrib-less": "~0.11.3", - "grunt-contrib-qunit": "~0.5.1", - "grunt-contrib-uglify": "~0.5.0", + "grunt-autoprefixer": "~3.0.0", + "grunt-contrib-clean": "~0.6.0", + "grunt-contrib-compress": "~0.13.0", + "grunt-contrib-concat": "~0.5.1", + "grunt-contrib-connect": "~0.10.1", + "grunt-contrib-copy": "~0.8.0", + "grunt-contrib-csslint": "~0.4.0", + "grunt-contrib-cssmin": "~0.12.3", + "grunt-contrib-htmlmin": "~0.4.0", + "grunt-contrib-jade": "~0.14.1", + "grunt-contrib-jshint": "~0.11.2", + "grunt-contrib-less": "~1.0.1", + "grunt-contrib-qunit": "~0.7.0", + "grunt-contrib-uglify": "~0.9.1", "grunt-contrib-watch": "~0.6.1", - "grunt-csscomb": "~2.0.1", - "grunt-exec": "~0.4.5", - "grunt-html-validation": "~0.1.18", + "grunt-csscomb": "~3.0.0", + "grunt-exec": "~0.4.6", + "grunt-html": "~4.0.3", "grunt-jekyll": "~0.4.2", - "grunt-jscs-checker": "~0.6.0", - "grunt-saucelabs": "~8.1.0", - "grunt-sed": "~0.1.1", - "load-grunt-tasks": "~0.6.0", - "markdown": "~0.5.0", - "npm-shrinkwrap": "~3.1.6", - "time-grunt": "~0.3.2" + "grunt-jscs": "~1.8.0", + "grunt-saucelabs": "~8.6.1", + "grunt-sed": "twbs/grunt-sed#v0.2.0", + "load-grunt-tasks": "~3.2.0", + "markdown-it": "^4.2.1", + "npm-shrinkwrap": "^200.4.0", + "time-grunt": "^1.2.0" }, "engines": { - "node": "~0.10.1" + "node": ">=0.10.1" }, + "files": [ + "dist", + "fonts", + "grunt", + "js/*.js", + "less/**/*.less", + "Gruntfile.js", + "LICENSE" + ], "jspm": { "main": "js/bootstrap", - "directories": { - "example": "examples", - "lib": "dist" - }, "shim": { "js/bootstrap": { - "imports": "jquery", + "deps": "jquery", "exports": "$" } }, - "buildConfig": { - "uglify": true - } + "files": [ + "css", + "fonts", + "js" + ] } } diff --git a/bower_components/jquery-colorbox/.bower.json b/bower_components/jquery-colorbox/.bower.json index 97051dd..725e5a9 100644 --- a/bower_components/jquery-colorbox/.bower.json +++ b/bower_components/jquery-colorbox/.bower.json @@ -1,17 +1,17 @@ { "name": "jquery-colorbox", "description": "jQuery lightbox and modal window plugin", - "version": "1.5.13", + "version": "1.6.1", "dependencies": { "jquery": ">=1.3.2" }, "keywords": [ "modal", "lightbox", - "window", + "gallery", "popup", "ui", - "jQuery" + "jquery-plugin" ], "authors": [ { @@ -38,13 +38,13 @@ "example4/index.html", "example5/index.html" ], - "_release": "1.5.13", + "_release": "1.6.1", "_resolution": { "type": "version", - "tag": "1.5.13", - "commit": "0662982e27789d0c48c3c82a5b787b47f2f701cd" + "tag": "1.6.1", + "commit": "b817f48e5b8e5fa694020ef5fe2ccfd76d2bf4f0" }, "_source": "git://github.com/jackmoore/colorbox.git", - "_target": "~1.5.10", + "_target": "~1.6.0", "_originalSource": "jquery-colorbox" }
\ No newline at end of file diff --git a/bower_components/jquery-colorbox/README.md b/bower_components/jquery-colorbox/README.md index 126274b..0698ce2 100644 --- a/bower_components/jquery-colorbox/README.md +++ b/bower_components/jquery-colorbox/README.md @@ -3,281 +3,297 @@ A customizable lightbox plugin for jQuery. See the [project page](http://jacklm ## Changelog: -### Version 1.5.13 - 2014/8/4 +##### Version 1.6.1 - 2015/05/14 + +* Replaced the inline onclick handler for cboxPhoto with a namespaced event for easier unbinding. Fixes #719. + +##### Version 1.6.0 - 2015/03/03 + +* Added two new properties that expose how `<img>` and `<iframe>` elements are created, to give users direct control over those elements. Fixes #700. + +##### Version 1.5.15 - 2015/02/25 + +* Adding to NPM, merged white-space cleanup & new language file. + +##### Version 1.5.14 - 2014/9/9 + +* When opening, append Colorbox to the DOM if it was detached for whatever reason. Fixes #645. + +##### Version 1.5.13 - 2014/8/4 * Fixed regression introduced with v1.5.12 with legacy versions of jQuery (1.3x-1.6x). References #628. -### Version 1.5.12 - 2014/7/31 +##### Version 1.5.12 - 2014/7/31 * Allowed setting the overlay opacity via CSS, by setting Colorbox's opacity property to false. References #628. -### Version 1.5.11 - 2014/7/31 +##### Version 1.5.11 - 2014/7/31 * Fixed bug where setting opacity to 0 was ignored. Fixes #628. -### Version 1.5.10 - 2014/6/26 +##### Version 1.5.10 - 2014/6/26 * Minor misc. tweaks (merging pull requests #611, #612, #615, #619, #620). -### Version 1.5.9 - 2014/4/25 +##### Version 1.5.9 - 2014/4/25 * Fixed inline content bug when using child selectors. Fixes #599 -### Version 1.5.8 - 2014/4/15 +##### Version 1.5.8 - 2014/4/15 * Fixed accidental leak of global variable. References #591 * Enabled strict mode. Fixes #597 -### Version 1.5.7 - 2014/4/15 +##### Version 1.5.7 - 2014/4/15 * Fix potential error when calling Colorbox directly. References #591 * Potentially worked around browser limitation of reporting that an image height and width is 0 immediately after onload. Fixes #535 -### Version 1.5.6 - 2014/4/4 +##### Version 1.5.6 - 2014/4/4 * Applied maxWidth and maxHeight to the initialWidth and initialHeight. Fixes #391 -### Version 1.5.5 - 2014/3/13 +##### Version 1.5.5 - 2014/3/13 * Allow setting the overlay opacity through CSS, rather than having to use Colorbox's opacity property. Fixes #580 -### Version 1.5.4 - 2014/3/7 +##### Version 1.5.4 - 2014/3/7 * Fixed potential issue where IE9+ wouldn't close the modal when clicking on the overlay. Fixes #576 -### Version 1.5.3 - 2014/3/4 +##### Version 1.5.3 - 2014/3/4 * Added access to settings object in callbacks. -### Version 1.5.2 - 2014/2/28 +##### Version 1.5.2 - 2014/2/28 * Added svg to image types regex. -### Version 1.5.1 - 2014/2/27 +##### Version 1.5.1 - 2014/2/27 * Fixed regression that broke direct calls to Colorbox, ie. $.colorbox(…) -### Version 1.5.0 - 2014/2/27 +##### Version 1.5.0 - 2014/2/27 * Changed when the className is applied: immediately on open, but only updated immediately prior to transition. Fixes #565 * Fixed potential style flash if #cboxLoadedContent is given a background. Fixes #567 * Misc. code cleanup -### Version 1.4.37 - 2014/2/11 +##### Version 1.4.37 - 2014/2/11 * Fixed potential error when resizing. Fixes #254 * Added Microsoft's JPEG XR to photo detection regex. -### Version 1.4.33 - 2013/10/31 +##### Version 1.4.33 - 2013/10/31 * Fixed an issue where private events propagated to the document in versions of jQuery prior to 1.7. Fixes #525, Fixes #526 -### Version 1.4.32 - 2013/10/16 +##### Version 1.4.32 - 2013/10/16 * Updated stylesheets to avoid issue with using `div {max-width:100%}` (Fixes #520) -### Version 1.4.31 - 2013/9/25 +##### Version 1.4.31 - 2013/9/25 * Used setAttribute to set londesc, so that the value is accessible via DOM Node longDesc property #508 -### Version 1.4.30 - 2013/9/24 +##### Version 1.4.30 - 2013/9/24 * Added longdesc and aria-describedby attributes to photos. Fixes #508 -### Version 1.4.29 - 2013/9/10 +##### Version 1.4.29 - 2013/9/10 * Fixed a slideshow regression from 1.4.27 * Fixed a potential issue with the starting size of #cboxLoadedContent -### Version 1.4.28 - 2013/9/4 +##### Version 1.4.28 - 2013/9/4 * Fixed a potential issue with using the open property with mixed slideshow and non-slideshow groups -### Version 1.4.27 - 2013/7/16 +##### Version 1.4.27 - 2013/7/16 * Fixed a width calculation issue relating to using margin:auto on #cboxLoadedContent. -### Version 1.4.26 - 2013/6/30 +##### Version 1.4.26 - 2013/6/30 * Fixed a regression in IE7 and IE8 that was causing an error. -### Version 1.4.25 - 2013/6/28 +##### Version 1.4.25 - 2013/6/28 * Use an animation speed of zero between same-sized content (fixed). * Removed temporary fix for jQuery UI 1.8 -### Version 1.4.24 - 2013/6/24 +##### Version 1.4.24 - 2013/6/24 * Added closeButton option. Set to false to remove the close button. -### Version 1.4.23 - 2013/6/23 +##### Version 1.4.23 - 2013/6/23 * Bugfix loading overlay/graphic append order -### Version 1.4.22 - 2013/6/19 +##### Version 1.4.22 - 2013/6/19 * Updated manifest files for the jQuery plugin repository and Bower (no changes to plugin) -### Version 1.4.21 - 2013/6/6 +##### Version 1.4.21 - 2013/6/6 * Replaced new Image() with document.createElement('img') to avoid a potential bug in Chrome 27. -### Version 1.4.20 - 2013/6/5 +##### Version 1.4.20 - 2013/6/5 * Fixing bug/typo from last update. -### Version 1.4.19 - 2013/6/3 +##### Version 1.4.19 - 2013/6/3 * Fixed bug where Colorbox was capturing ctrl+click on assigned links on windows browsers with jQuery 1.7+, rather than ignoring. -### Version 1.4.18 - 2013/5/30 +##### Version 1.4.18 - 2013/5/30 * Fixed a scroll position issue when using $.colorbox.resize() -### Version 1.4.17 - 2013/5/23 +##### Version 1.4.17 - 2013/5/23 * Possible fix for a Chrome 27 issue (https://github.com/jackmoore/colorbox/pull/438#issuecomment-18334804) -### Version 1.4.16 - 2013/5/20 +##### Version 1.4.16 - 2013/5/20 * Added trapFocus setting to allow disabling of focus trapping -### Version 1.4.15 - 2013/4/22 +##### Version 1.4.15 - 2013/4/22 * Added .webp to list of recognized image extensions -### Version 1.4.14 - 2013/4/16 +##### Version 1.4.14 - 2013/4/16 * Added fadeOut property to control the closing fadeOut speed. * Removed longdesc attribute for now. -### Version 1.4.13 - 2013/4/11 +##### Version 1.4.13 - 2013/4/11 * Fixed an error involving IE7/IE8 and legacy versions of jQuery -### Version 1.4.12 - 2013/4/9 +##### Version 1.4.12 - 2013/4/9 * Fixed a potential conflict with Twitter Bootstrap default img styles. -### Version 1.4.11 - 2013/4/9 +##### Version 1.4.11 - 2013/4/9 * Added `type='button'` to buttons to prevent accidental form submission * Added alt and longdesc attributes to photo content if they are present on the calling element. -### Version 1.4.10 - 2013/4/2 +##### Version 1.4.10 - 2013/4/2 * Better 'old IE' feature detection that fixes an error with jQuery 2.0.0pre. -### Version 1.4.9 - 2013/4/2 +##### Version 1.4.9 - 2013/4/2 * Fixes bug introduced in previous version. -### Version 1.4.8 - 2013/4/2 +##### Version 1.4.8 - 2013/4/2 * Dropped IE6 support. * Fixed other issues with $.colorbox.remove. -### Version 1.4.7 - 2013/4/1 +##### Version 1.4.7 - 2013/4/1 * Prevented an error if $.colorbox.remove is called during the transition. -### Version 1.4.6 - 2013/3/19 +##### Version 1.4.6 - 2013/3/19 * Minor change to work around a jQuery 1.4.2 bug for legacy users. -### Version 1.4.5 - 2013/3/10 +##### Version 1.4.5 - 2013/3/10 * Minor change to apply the close and className properties sooner. -### Version 1.4.4 - 2013/3/10 +##### Version 1.4.4 - 2013/3/10 * Fixed an issue with percent-based heights in iOS * Fixed an issue with ajax requests being applied at the wrong time. -### Version 1.4.3 - 2013/2/18 +##### Version 1.4.3 - 2013/2/18 * Made image preloading aware of retina settings. -### Version 1.4.2 - 2013/2/18 +##### Version 1.4.2 - 2013/2/18 * Removed $.contains for compatibility with jQuery 1.3.x -### Version 1.4.1 - 2013/2/14 +##### Version 1.4.1 - 2013/2/14 * Ignored left and right arrow keypresses if combined with the alt key. -### Version 1.4.0 - 2013/2/12 +##### Version 1.4.0 - 2013/2/12 * Better accessibility: * Replaced div controls with buttons * Tabbed navigation confined to modal window * Added aria role -### Version 1.3.34 - 2013/2/4 +##### Version 1.3.34 - 2013/2/4 * Updated manifest for plugins.jquery.com -### Version 1.3.33 - 2013/2/4 +##### Version 1.3.33 - 2013/2/4 * Added retina display properties: retinaImage, retinaUrl, retinaSuffix * Fixed iframe scrolling on iOS devices. -### Version 1.3.32 - 2013/1/31 +##### Version 1.3.32 - 2013/1/31 * Improved internal event subscribing & fixed event bug introduced in v1.3.21 -### Version 1.3.31 - 2013/1/28 +##### Version 1.3.31 - 2013/1/28 * Fixed a size-calculation bug introduced in the previous commit. -### Version 1.3.30 - 2013/1/25 +##### Version 1.3.30 - 2013/1/25 * Delayed border-width calculations until after opening, to avoid a bug in FF when using Colorbox in a hidden iframe. -### Version 1.3.29 - 2013/1/24 +##### Version 1.3.29 - 2013/1/24 * Fixes bug with bubbling delegated events, introduced in the previous commit. -### Version 1.3.28 - 2013/1/24 +##### Version 1.3.28 - 2013/1/24 * Fixed compatibility issue with old versions of jQuery (1.3.2-1.4.2) -### Version 1.3.27 - 2013/1/23 +##### Version 1.3.27 - 2013/1/23 * Added className property. -### Version 1.3.26 - 2013/1/23 +##### Version 1.3.26 - 2013/1/23 * Minor bugfix: clear the onload event handler after photo has loaded. -### Version 1.3.25 - 2013/1/23 +##### Version 1.3.25 - 2013/1/23 * Removed grunt file & added Bower component.json. -### Version 1.3.24 - 2013/1/22 +##### Version 1.3.24 - 2013/1/22 * Added generated files (jquery.colorbox.js / jquery.colorbox-min.js) back to the repository. -### Version 1.3.23 - 2013/1/18 +##### Version 1.3.23 - 2013/1/18 * Minor bugfix for calling Colorbox on empty jQuery collections without a selector. -### Version 1.3.22 - 2013/1/17 +##### Version 1.3.22 - 2013/1/17 * Recommit for plugins.jquery.com -### Version 1.3.21 - 2013/1/15 +##### Version 1.3.21 - 2013/1/15 Files Changed: *.js * Fixed compatibility issues with jQuery 1.9 -### Version 1.3.20 - August 15 2012 +##### Version 1.3.20 - August 15 2012 Files Changed:jquery.colorbox.js * Added temporary workaround for jQuery-UI 1.8 bug (http://bugs.jquery.com/ticket/12273) * Added *.jpe extension to the list of image types. -### Version 1.3.19 - December 08 2011 +##### Version 1.3.19 - December 08 2011 Files Changed:jquery.colorbox.js, colorbox.css (all) * Fixed bug related to using the 'fixed' property. @@ -285,7 +301,7 @@ Files Changed:jquery.colorbox.js, colorbox.css (all) * Removed $.colorbox.init() as it will no longer be needed (will self-init when called). * Removed use of $.browser. -### Version 1.3.18 - October 07 2011 +##### Version 1.3.18 - October 07 2011 Files Changed:jquery.colorbox.js/jquery.colorbox-min.js, colorbox.css (all) and example 1's controls.png * Fixed a regression where Flash content displayed in Colorbox would be reloaded if the browser window was resized. @@ -294,7 +310,7 @@ Files Changed:jquery.colorbox.js/jquery.colorbox-min.js, colorbox.css (all) and * Changed the slideshow behavior so that it immediately moves to the next slide when the slideshow is started. * Minor regex bugfix to allow automatic detection of image URLs that include fragments. -### Version 1.3.17 - May 11 2011 +##### Version 1.3.17 - May 11 2011 Files Changed:jquery.colorbox.js/jquery.colorbox-min.js * Added properties "top", "bottom", "left" and "right" to specify a position relative to the viewport, rather than using the default centering. @@ -303,7 +319,7 @@ Files Changed:jquery.colorbox.js/jquery.colorbox-min.js * Fixed ClearType problem with IE7. * Minor fixes. -### Version 1.3.16 - March 01 2011 +##### Version 1.3.16 - March 01 2011 Files Changed:jquery.colorbox.js/jquery.colorbox-min.js, colorbox.css (all) and example 4 background png files * Better IE related transparency workarounds. IE7 and up now uses the same background image sprite as other browsers. @@ -311,35 +327,35 @@ Files Changed:jquery.colorbox.js/jquery.colorbox-min.js, colorbox.css (all) and * Added new property: 'fastIframe' and set it to true by default. Setting to fastIframe:false will delay the loading graphic removal and onComplete event until iframe has completely loaded. * Ability to redefine $.colorbox.close (or prev, or next) at any time. -### Version 1.3.15 - October 27 2010 +##### Version 1.3.15 - October 27 2010 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Minor fixes for specific cases. -### Version 1.3.14 - October 27 2010 +##### Version 1.3.14 - October 27 2010 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * In IE6, closing an iframe when using HTTPS no longer generates a security warning. -### Version 1.3.13 - October 22 2010 +##### Version 1.3.13 - October 22 2010 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Changed the index.html example files to use YouTube's new embedded link format. * By default, Colorbox returns focus to the element it was launched from once it closes. This can now be disabled by setting the 'returnFocus' property to false. Focus was causing problems for some users who had their anchor elements inside animated containers. * Minor bug fix involved in using a combination of slideshow and non-slideshow content. -### Version 1.3.12 - October 20 2010 +##### Version 1.3.12 - October 20 2010 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Minor bug fix involved in preloading images when using a function as a value for the href property. -### Version 1.3.11 - October 19 2010 +##### Version 1.3.11 - October 19 2010 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Fixed the slideshow functionality that broke with 1.3.10 * The slideshow now respects the loop property. -### Version 1.3.10 - October 16 2010 +##### Version 1.3.10 - October 16 2010 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Fixed compatibility with jQuery 1.4.3 @@ -349,14 +365,14 @@ Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * May have fixed an issue in Opera 10.6+ where Colorbox would rarely/randomly freeze up while switching between photos in a group. * Some functionality better encapsulated & minor performance improvements. -### Version 1.3.9 - July 7 2010 +##### Version 1.3.9 - July 7 2010 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js/ all colorbox.css (the core styles) * Fixed a problem where iframed youtube videos would cause a security alert in IE. * More code is event driven now, making the source easier to grasp. * Removed some unnecessary style from the core CSS. -### Version 1.3.8 - June 21 2010 +##### Version 1.3.8 - June 21 2010 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Fixed a bug in Chrome where it would sometimes render photos at 0 by 0 width and height (behavior introduced in recent update to Chrome). @@ -365,7 +381,7 @@ Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Abstracted the identifiers (HTML ids & classes, and JS plugin name, method, and events) so that the plugin can be easily rebranded. * Small changes to improve either code readability or compression. -### Version 1.3.7 - June 13 2010 +##### Version 1.3.7 - June 13 2010 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js/index.html * $.colorbox can now be used for direct calls and accessing public methods. Example: $.colorbox.close(); @@ -377,19 +393,19 @@ Files Changed: jquery.colorbox.js/jquery.colorbox-min.js/index.html * Now uses the exact href specified on an anchor, rather than the version returned by 'this.href'. This was causing "#example" to be normalized to "http://domain/#example" which interfered with how some users were setting up links to inline content. * Changed example documents over to HTML5. -### Version 1.3.6 - Jan 13 2010 +##### Version 1.3.6 - Jan 13 2010 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Small change to make Colorbox compatible with jQuery 1.4 -### Version 1.3.5 - December 15 2009 +##### Version 1.3.5 - December 15 2009 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Fixed a bug introduced in 1.3.4 with IE7's display of example 2 and 3, and auto-width in Opera. * Fixed a bug introduced in 1.3.4 where colorbox could not be launched by triggering an element's click event through JavaScript. * Minor refinements. -### Version 1.3.4 - December 5 2009 +##### Version 1.3.4 - December 5 2009 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Event delegation is now used for elements that Colorbox is assigned to, rather than individual click events. @@ -399,13 +415,13 @@ Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Fixed a bug where maxHeight and maxWidth did not work for non-photo content. * Direct calls no longer need 'open:true', it is assumed. Example: `$.colorbox({html:'<p>Hi</p>'});` -### Version 1.3.3 - November 7 2009 +##### Version 1.3.3 - November 7 2009 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Changed $.colorbox.element() to return a jQuery object rather the DOM element. * jQuery.colorbox-min.js is compressed with Google's Closure Compiler rather than YUI Compressor. -### Version 1.3.2 - October 27 2009 +##### Version 1.3.2 - October 27 2009 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Added 'innerWidth' and 'innerHeight' options to allow people to easily set the size dimensions for Colorbox, without having to anticipate the size of the borders and buttons. @@ -415,13 +431,13 @@ Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Bug fix: In Firefox, opening Colorbox causes a split second shift with a small minority of webpage layouts. * Simplified code in a few areas. -### Version 1.3.1 - September 16 2009 +##### Version 1.3.1 - September 16 2009 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js/colorbox.css/colorbox-ie.css(removed) * Removed the IE-only stylesheets and conditional comments for example styles 1 & 4. All CSS is handled by a single CSS file for all examples. * Removed user-agent sniffing from the js and replaced it with feature detection. This will allow correct rendering for visitors masking their agent type. -### Version 1.3.0 - September 15 2009 +##### Version 1.3.0 - September 15 2009 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js/colorbox.css * Added $.colorbox.resize() method to allow Colorbox to resize it's height if it's contents change. @@ -432,20 +448,20 @@ Files Changed: jquery.colorbox.js/jquery.colorbox-min.js/colorbox.css * Fixed a bug where ClearType may not work in IE6&7 if using the fade transition. * Minor code optimizations to increase compression. -### Version 1.2.9 - August 7 2009 +##### Version 1.2.9 - August 7 2009 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Minor change to enable use with $.getScript(); * Minor change to the timing of the 'cbox_load' event so that it is more useful. * Added a direct link to a YouTube video to the examples. -### Version 1.2.8 - August 5 2009 +##### Version 1.2.8 - August 5 2009 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Fixed a bug with the overlay in IE6 * Fixed a bug where left & right keypress events might be prematurely unbound. -### Version 1.2.7 - July 31 2009 +##### Version 1.2.7 - July 31 2009 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js, example stylesheets and background images (core styles have not changed and the updates will not affect existing user themes / old example themes) * Code cleanup and reduction, better organization and documentation in the full source. @@ -460,7 +476,7 @@ Files Changed: jquery.colorbox.js/jquery.colorbox-min.js, example stylesheets an * Optimized pngs for smaller file size. * Added slices, grid, and correct sizing to the Adobe Illustrator file, all theme files are now export ready! -### Version 1.2.6 - July 15 2009 +##### Version 1.2.6 - July 15 2009 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Fixed a bug with fixed width/height images in Opera 9.64. @@ -468,29 +484,29 @@ Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Changed how href/rel/title settings are determined to avoid users having to manually update Colorbox settings if they use JavaScript to update any of those attributes, after Colorbox has been defined. * Fixed a FF3 bug where the back button was disabled after closing an iframe. -### Version 1.2.5 - June 23 2009 +##### Version 1.2.5 - June 23 2009 Files Changed: jquery.colorbox.js/jquery.colorbox-min.js * Changed the point at which iframe srcs are set (to eliminate the need to refresh the iframe once it has been added to the DOM). * Removed unnecessary return values for a very slight code reduction. -### Version 1.2.4 - June 9 2009 +##### Version 1.2.4 - June 9 2009 Files Changed: jquery.colorbox.js, jquery.colorbox-min.js * Fixed an issue where Colorbox may not close completely if it is closed during a transition animation. * Minor code reduction. -### Version 1.2.3 - June 4 2009 +##### Version 1.2.3 - June 4 2009 * Fixed a png transparency stacking issue in IE. * More accurate Ajax auto-sizing if the user was depending on the #cboxLoadedContent ID for CSS styling. * Added a public function for returning the current html element that Colorbox is associated with. Example use: var that = $.colorbox.element(); * Added bicubic scaling for resized images in the original IE7. * Removed the IE6 stylesheet and png files from Example 3. It now uses the same png file for the controls that the rest of the browsers use (an alpha transparency PNG8). This example now only has 2 graphics files and 1 stylesheet. -### Version 1.2.2 - May 28 2009 +##### Version 1.2.2 - May 28 2009 * Fixed an issue with the 'resize' option. -### Version 1.2.1 - May 28 2009 +##### Version 1.2.1 - May 28 2009 * Note: If you are upgrading, update your jquery.colorbox.js and colorbox.css files. * Added photo resizing. * Added a maximum width and maximum height. Example: {height:800, maxHeight:'100%'}, would allow the box to be a maximum potential height of 800px, instead of a fixed height of 800px. With maxHeight of 100% the height of Colorbox cannot exceed the height of the browser window. @@ -503,7 +519,7 @@ Files Changed: jquery.colorbox.js, jquery.colorbox-min.js * Fixed a minor grouping issue with IE6, when transition type is set to 'none'. * Added an Adobe Illustrator file that contains the borders and buttons used in the various examples. -### Version 1.2 - May 13 2009 +##### Version 1.2 - May 13 2009 * Added a slideshow feature. * Added re-positioning on browser resize. If the browser is resized, Colorbox will recenter itself onscreen. * Added hooks for key events: cbox_open, cbox_load, cbox_complete, cbox_closed. @@ -519,23 +535,23 @@ Files Changed: jquery.colorbox.js, jquery.colorbox-min.js * Changed the naming of variables in the parameter map to be more concise and intuitive. * Removed colorbox.css. Combined the colorbox.css styles with jquery.colorbox.js: the css file was not large enough to warrant being a separate file. -### Version 1.1.6 - April 28 2009 +##### Version 1.1.6 - April 28 2009 * Prevented the default action of the next & previous anchors and the left and right keys for gallery mode. * Fixed a bug where the title element was being added back to the DOM when closing Colorbox while using inline content. * Fixed a bug where IE7 would crash for example 2. * Smaller filesize: removed a small amount of unused code and rewrote the HTML injection with less syntax. * Added a public method for closing Colorbox: $.colorbox.close(). This will allow iframe users to add an event to close Colorbox without having to create an additional function. -### Version 1.1.5 - April 11 2009 +##### Version 1.1.5 - April 11 2009 * Fixed minor issues with exiting Colorbox. -### Version 1.1.4 - April 08 2009 +##### Version 1.1.4 - April 08 2009 * Fixed a bug in the fade transition where Colorbox not close completely if instructed to close during the fade-in portion of the transition. -### Version 1.1.3 - April 06 2009 +##### Version 1.1.3 - April 06 2009 * Fixed an IE6&7 issue with using Colorbox to display animated GIFs. -### Version 1.1.2 - April 05 2009 +##### Version 1.1.2 - April 05 2009 * Added ability to change content when Colorbox is already open. * Added vertical photo centering now works for all browsers (this feature previously excluded IE6&7). * Added namespacing to the esc-key keydown event for people who want to disable it: "keydown.colorClose" @@ -545,13 +561,13 @@ Files Changed: jquery.colorbox.js, jquery.colorbox-min.js * Fixed a bug in the fade transition where the border would still come up if Colorbox was closed mid-transition. * Switch from JSMin to Yui Compressor for minification. Minified code now under 7KB. -### Version 1.1.1 - March 31 2009 +##### Version 1.1.1 - March 31 2009 * More robust image detection regex. Now detects image file types with url fragments and/or query strings. * Added 'nofollow' exception to rel grouping. * Changed how images are loaded into the DOM to prevent premature size calculation by Colorbox. * Added timestamp to iframe name to prevent caching - this was a problem in some browsers if the user had multiple iframes and the visitor left the page and came back, or if they refreshed the page. -### Version 1.1.0 - March 21 2009 +##### Version 1.1.0 - March 21 2009 * Animation is now much smoother and less resource intensive. * Added support for % sizing. * Callback option added. @@ -571,22 +587,22 @@ Files Changed: jquery.colorbox.js, jquery.colorbox-min.js * Added a minified version. * Code passes JSLint. -### Version 1.0.5 - March 11 2009 +##### Version 1.0.5 - March 11 2009 * Redo: Fixed a bug where IE would cut off the bottom portion of a photo, if the photo was larger than the document dimensions. -### Version 1.0.4 - March 10 2009 +##### Version 1.0.4 - March 10 2009 * Added an option to allow users to automatically open the lightbox. Example usage: $(".colorbox").colorbox({open:true}); * Fixed a bug where IE would cut off the bottom portion of a photo, if the photo was larger than the document dimensions. -### Version 1.0.3 - March 09 2009 +##### Version 1.0.3 - March 09 2009 * Fixed vertical centering for Safari 3.0.x. -### Version 1.0.2 - March 06 2009 +##### Version 1.0.2 - March 06 2009 * Corrected a typo. * Changed the content-type check so that it does not assume all links to photos should actually display photos. This allows for Ajax/inline/and iframe calls on anchors linking to picture file types. -### Version 1.0.1 - March 05 2009 +##### Version 1.0.1 - March 05 2009 * Fixed keydown events (esc, left arrow, right arrow) for Webkit browsers. -### Version 1.0 - March 03 2009 +##### Version 1.0 - March 03 2009 * First release diff --git a/bower_components/jquery-colorbox/bower.json b/bower_components/jquery-colorbox/bower.json index 5123d5b..ab71158 100644 --- a/bower_components/jquery-colorbox/bower.json +++ b/bower_components/jquery-colorbox/bower.json @@ -1,17 +1,17 @@ { "name": "jquery-colorbox", "description": "jQuery lightbox and modal window plugin", - "version": "1.5.13", + "version": "1.6.1", "dependencies": { "jquery": ">=1.3.2" }, "keywords": [ "modal", "lightbox", - "window", + "gallery", "popup", "ui", - "jQuery" + "jquery-plugin" ], "authors": [ { diff --git a/bower_components/jquery-colorbox/example1/images/border.png b/bower_components/jquery-colorbox/example1/images/border.png Binary files differindex f463a10..9386f35 100644 --- a/bower_components/jquery-colorbox/example1/images/border.png +++ b/bower_components/jquery-colorbox/example1/images/border.png diff --git a/bower_components/jquery-colorbox/example1/images/controls.png b/bower_components/jquery-colorbox/example1/images/controls.png Binary files differindex dcfd6fb..1ec3cb1 100644 --- a/bower_components/jquery-colorbox/example1/images/controls.png +++ b/bower_components/jquery-colorbox/example1/images/controls.png diff --git a/bower_components/jquery-colorbox/example1/images/loading.gif b/bower_components/jquery-colorbox/example1/images/loading.gif Binary files differindex b4695d8..0325c8d 100644 --- a/bower_components/jquery-colorbox/example1/images/loading.gif +++ b/bower_components/jquery-colorbox/example1/images/loading.gif diff --git a/bower_components/jquery-colorbox/example1/images/loading_background.png b/bower_components/jquery-colorbox/example1/images/loading_background.png Binary files differindex 6ae83e6..23a336b 100644 --- a/bower_components/jquery-colorbox/example1/images/loading_background.png +++ b/bower_components/jquery-colorbox/example1/images/loading_background.png diff --git a/bower_components/jquery-colorbox/example1/images/overlay.png b/bower_components/jquery-colorbox/example1/images/overlay.png Binary files differindex 53ea98f..10362a4 100644 --- a/bower_components/jquery-colorbox/example1/images/overlay.png +++ b/bower_components/jquery-colorbox/example1/images/overlay.png diff --git a/bower_components/jquery-colorbox/example2/images/controls.png b/bower_components/jquery-colorbox/example2/images/controls.png Binary files differindex 8569b57..36f5269 100644 --- a/bower_components/jquery-colorbox/example2/images/controls.png +++ b/bower_components/jquery-colorbox/example2/images/controls.png diff --git a/bower_components/jquery-colorbox/example2/images/loading.gif b/bower_components/jquery-colorbox/example2/images/loading.gif Binary files differindex 19c67bb..a32df5c 100644 --- a/bower_components/jquery-colorbox/example2/images/loading.gif +++ b/bower_components/jquery-colorbox/example2/images/loading.gif diff --git a/bower_components/jquery-colorbox/example3/images/loading.gif b/bower_components/jquery-colorbox/example3/images/loading.gif Binary files differindex 19c67bb..a32df5c 100644 --- a/bower_components/jquery-colorbox/example3/images/loading.gif +++ b/bower_components/jquery-colorbox/example3/images/loading.gif diff --git a/bower_components/jquery-colorbox/example4/images/border1.png b/bower_components/jquery-colorbox/example4/images/border1.png Binary files differindex 0ddc704..ea73e15 100644 --- a/bower_components/jquery-colorbox/example4/images/border1.png +++ b/bower_components/jquery-colorbox/example4/images/border1.png diff --git a/bower_components/jquery-colorbox/example4/images/border2.png b/bower_components/jquery-colorbox/example4/images/border2.png Binary files differindex aa62a0b..72cad44 100644 --- a/bower_components/jquery-colorbox/example4/images/border2.png +++ b/bower_components/jquery-colorbox/example4/images/border2.png diff --git a/bower_components/jquery-colorbox/example4/images/loading.gif b/bower_components/jquery-colorbox/example4/images/loading.gif Binary files differindex 602ce3c..1f3a2c0 100644 --- a/bower_components/jquery-colorbox/example4/images/loading.gif +++ b/bower_components/jquery-colorbox/example4/images/loading.gif diff --git a/bower_components/jquery-colorbox/example5/images/border.png b/bower_components/jquery-colorbox/example5/images/border.png Binary files differindex df13bb6..c1cd1a2 100644 --- a/bower_components/jquery-colorbox/example5/images/border.png +++ b/bower_components/jquery-colorbox/example5/images/border.png diff --git a/bower_components/jquery-colorbox/example5/images/controls.png b/bower_components/jquery-colorbox/example5/images/controls.png Binary files differindex 65cfd1d..259130c 100644 --- a/bower_components/jquery-colorbox/example5/images/controls.png +++ b/bower_components/jquery-colorbox/example5/images/controls.png diff --git a/bower_components/jquery-colorbox/example5/images/loading.gif b/bower_components/jquery-colorbox/example5/images/loading.gif Binary files differindex b4695d8..dba33c8 100644 --- a/bower_components/jquery-colorbox/example5/images/loading.gif +++ b/bower_components/jquery-colorbox/example5/images/loading.gif diff --git a/bower_components/jquery-colorbox/example5/images/loading_background.png b/bower_components/jquery-colorbox/example5/images/loading_background.png Binary files differindex 9de11f4..23a336b 100644 --- a/bower_components/jquery-colorbox/example5/images/loading_background.png +++ b/bower_components/jquery-colorbox/example5/images/loading_background.png diff --git a/bower_components/jquery-colorbox/i18n/jquery.colorbox-bn.js b/bower_components/jquery-colorbox/i18n/jquery.colorbox-bn.js new file mode 100644 index 0000000..946229d --- /dev/null +++ b/bower_components/jquery-colorbox/i18n/jquery.colorbox-bn.js @@ -0,0 +1,16 @@ +/* +jQuery Colorbox language configuration +language: Bengali (bn) +translated by: Arkaprava Majumder +http://github.com/arkaindas +*/ +jQuery.extend(jQuery.colorbox.settings, { +current: "ছবি {current} এর {total}", +previous: "আগে", +next: "পরে", +close: "বন্ধ", +xhrError: "এই কন্টেন্ট লোড করা যায়নি.", +imgError: "এই ছবিটি লোড করা যায়নি.", +slideshowStart: "স্লাইডশো শুরু", +slideshowStop: "স্লাইডশো বন্ধ" +}); diff --git a/bower_components/jquery-colorbox/i18n/jquery.colorbox-pt-br.js b/bower_components/jquery-colorbox/i18n/jquery.colorbox-pt-BR.js index 73e948b..a405d93 100644 --- a/bower_components/jquery-colorbox/i18n/jquery.colorbox-pt-br.js +++ b/bower_components/jquery-colorbox/i18n/jquery.colorbox-pt-BR.js @@ -1,6 +1,6 @@ /* jQuery Colorbox language configuration - language: Brazilian Portuguese (pt-br) + language: Brazilian Portuguese (pt-BR) translated by: ReinaldoMT */ jQuery.extend(jQuery.colorbox.settings, { diff --git a/bower_components/jquery-colorbox/jquery.colorbox.js b/bower_components/jquery-colorbox/jquery.colorbox.js index dae8728..976d38e 100644 --- a/bower_components/jquery-colorbox/jquery.colorbox.js +++ b/bower_components/jquery-colorbox/jquery.colorbox.js @@ -1,8 +1,7 @@ /*! - Colorbox v1.5.13 - 2014-08-04 - jQuery lightbox and modal window plugin - (c) 2014 Jack Moore - http://www.jacklmoore.com/colorbox - license: http://www.opensource.org/licenses/mit-license.php + Colorbox 1.6.1 + license: MIT + http://www.jacklmoore.com/colorbox */ (function ($, document, window) { var @@ -86,6 +85,39 @@ }, title: function() { return this.title; + }, + createImg: function() { + var img = new Image(); + var attrs = $(this).data('cbox-img-attrs'); + + if (typeof attrs === 'object') { + $.each(attrs, function(key, val){ + img[key] = val; + }); + } + + return img; + }, + createIframe: function() { + var iframe = document.createElement('iframe'); + var attrs = $(this).data('cbox-iframe-attrs'); + + if (typeof attrs === 'object') { + $.each(attrs, function(key, val){ + iframe[key] = val; + }); + } + + if ('frameBorder' in iframe) { + iframe.frameBorder = 0; + } + if ('allowTransparency' in iframe) { + iframe.allowTransparency = "true"; + } + iframe.name = (new Date()).getTime(); // give the iframe a unique name to prevent caching + iframe.allowFullScreen = true; + + return iframe; } }, @@ -93,7 +125,7 @@ colorbox = 'colorbox', prefix = 'cbox', boxElement = prefix + 'Element', - + // Events event_open = prefix + '_open', event_load = prefix + '_load', @@ -124,7 +156,7 @@ $close, $groupControls, $events = $('<a/>'), // $({}) would be prefered, but there is an issue with jQuery 1.4.2 - + // Variables for cached values or use across multiple functions settings, interfaceHeight, @@ -146,7 +178,7 @@ // **************** // HELPER FUNCTIONS // **************** - + // Convenience function for creating new jQuery objects function $tag(tag, id, css) { var element = document.createElement(tag); @@ -161,7 +193,7 @@ return $(element); } - + // Get the window height using innerHeight when available to avoid an issue with iOS // http://bugs.jquery.com/ticket/6724 function winheight() { @@ -205,7 +237,7 @@ var max = $related.length, newIndex = (index + increment) % max; - + return (newIndex < 0) ? max + newIndex : newIndex; } @@ -213,7 +245,7 @@ function setSize(size, dimension) { return Math.round((/%/.test(size) ? ((dimension === 'x' ? $window.width() : winheight()) / 100) : 1) * parseInt(size, 10)); } - + // Checks an href to see if it is a photo. // There is a force photo option (photo: true) for hrefs that cannot be matched by the regex. function isImage(settings, url) { @@ -240,7 +272,7 @@ function getRelated(rel) { index = 0; - + if (rel && rel !== false && rel !== 'nofollow') { $related = $('.' + boxElement).filter(function () { var options = $.data(this, colorbox); @@ -248,7 +280,7 @@ return (settings.get('rel') === rel); }); index = $related.index(settings.el); - + // Check direct calls to Colorbox. if (index === -1) { $related = $related.add(settings.el); @@ -298,7 +330,7 @@ function stop() { clear(); - + $events .unbind(event_complete, set) .unbind(event_load, clear); @@ -355,17 +387,17 @@ options = $(element).data(colorbox); settings = new Settings(element, options); - + getRelated(settings.get('rel')); if (!open) { open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys. setClass(settings.get('className')); - + // Show colorbox so the sizes can be calculated in older versions of jQuery $box.css({visibility:'hidden', display:'block', opacity:''}); - + $loaded = $tag(div, 'LoadedContent', 'width:0; height:0; overflow:hidden; visibility:hidden'); $content.css({width:'', height:''}).append($loaded); @@ -393,14 +425,14 @@ $groupControls.add($title).hide(); $box.focus(); - + if (settings.get('trapFocus')) { // Confine focus to the modal // Uses event capturing that is not supported in IE8- if (document.addEventListener) { document.addEventListener('focus', trapFocus, true); - + $events.one(event_closed, function () { document.removeEventListener('focus', trapFocus, true); }); @@ -421,7 +453,7 @@ cursor: settings.get('overlayClose') ? 'pointer' : '', visibility: 'visible' }).show(); - + if (settings.get('closeButton')) { $close.html(settings.get('close')).appendTo($content); } else { @@ -435,7 +467,7 @@ // Colorbox's markup needs to be added to the DOM prior to being called // so that the browser will go ahead and load the CSS background images. function appendHTML() { - if (!$box && document.body) { + if (!$box) { init = false; $window = $(window); $box = $tag(div).attr({ @@ -457,7 +489,7 @@ ); $close = $('<button type="button"/>').attr({id:prefix+'Close'}); - + $wrap.append( // The 3x3 Grid that makes up Colorbox $tag(div).append( $tag(div, "TopLeft"), @@ -475,11 +507,12 @@ $tag(div, "BottomRight") ) ).find('div div').css({'float': 'left'}); - + $loadingBay = $tag(div, false, 'position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;'); - - $groupControls = $next.add($prev).add($current).add($slideshow); + $groupControls = $next.add($prev).add($current).add($slideshow); + } + if (document.body && !$box.parent().length) { $(document.body).append($overlay, $box.append($wrap, $loadingBay)); } } @@ -514,7 +547,7 @@ publicMethod.close(); } }); - + // Key Bindings $(document).bind('keydown.' + prefix, function (e) { var key = e.keyCode; @@ -562,7 +595,7 @@ // Usage format: $.colorbox.close(); // Usage from within an iframe: parent.jQuery.colorbox.close(); // **************** - + publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) { var settings; var $obj = this; @@ -572,15 +605,12 @@ if ($.isFunction($obj)) { // assume a call to $.colorbox $obj = $('<a/>'); options.open = true; - } else if (!$obj[0]) { // colorbox being applied to empty collection - return $obj; } - if (!$obj[0]) { // colorbox being applied to empty collection return $obj; } - + appendHTML(); if (addBindings()) { @@ -595,12 +625,12 @@ }).addClass(boxElement); settings = new Settings($obj[0], options); - + if (settings.get('open')) { launch($obj[0]); } } - + return $obj; }; @@ -612,7 +642,7 @@ offset = $box.offset(), scrollTop, scrollLeft; - + $window.unbind('resize.' + prefix); // remove the modal so that it doesn't influence the document width/height @@ -639,7 +669,7 @@ } else { left += Math.round(Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2); } - + if (settings.get('bottom') !== false) { top += Math.max(winheight() - settings.h - loadedHeight - interfaceHeight - setSize(settings.get('bottom'), 'y'), 0); } else if (settings.get('top') !== false) { @@ -649,12 +679,12 @@ } $box.css({top: offset.top, left: offset.left, visibility:'visible'}); - + // this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly, // but it has to be shrank down around the size of div#colorbox when it's done. If not, // it can invoke an obscure IE bug when using iframes. $wrap[0].style.width = $wrap[0].style.height = "9999px"; - + function modalDimensions() { $topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = (parseInt($box[0].style.width,10) - interfaceWidth)+'px'; $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = (parseInt($box[0].style.height,10) - interfaceHeight)+'px'; @@ -684,20 +714,20 @@ duration: speed || 0, complete: function () { modalDimensions(); - + active = false; - + // shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation. $wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px"; $wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px"; - + if (settings.get('reposition')) { setTimeout(function () { // small delay before binding onresize due to an IE8 bug. $window.bind('resize.' + prefix, publicMethod.position); }, 1); } - if (loadedCallback) { + if ($.isFunction(loadedCallback)) { loadedCallback(); } }, @@ -707,10 +737,10 @@ publicMethod.resize = function (options) { var scrolltop; - + if (open) { options = options || {}; - + if (options.width) { settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth; } @@ -720,7 +750,7 @@ } $loaded.css({width: settings.w}); - + if (options.height) { settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight; } @@ -740,7 +770,7 @@ if(scrolltop) { $loaded.scrollTop(scrolltop); } - + publicMethod.position(settings.get('transition') === "none" ? 0 : settings.get('speed')); } }; @@ -749,13 +779,13 @@ if (!open) { return; } - + var callback, speed = settings.get('transition') === "none" ? 0 : settings.get('speed'); $loaded.remove(); $loaded = $tag(div, 'LoadedContent').append(object); - + function getWidth() { settings.w = settings.w || $loaded.width(); settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w; @@ -766,17 +796,17 @@ settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h; return settings.h; } - + $loaded.hide() .appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations. .css({width: getWidth(), overflow: settings.get('scrolling') ? 'auto' : 'hidden'}) .css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height. .prependTo($content); - + $loadingBay.hide(); - + // floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width. - + $(photo).css({'float': 'none'}); setClass(settings.get('className')); @@ -785,17 +815,17 @@ var total = $related.length, iframe, complete; - + if (!open) { return; } - + function removeFilter() { // Needed for IE8 in versions of jQuery prior to 1.7.2 if ($.support.opacity === false) { $box[0].style.removeAttribute('filter'); } } - + complete = function () { clearTimeout(loadingTimer); $loadingOverlay.hide(); @@ -803,20 +833,20 @@ settings.get('onComplete'); }; - + $title.html(settings.get('title')).show(); $loaded.show(); - + if (total > 1) { // handle grouping if (typeof settings.get('current') === "string") { $current.html(settings.get('current').replace('{current}', index + 1).replace('{total}', total)).show(); } - + $next[(settings.get('loop') || index < total - 1) ? "show" : "hide"]().html(settings.get('next')); $prev[(settings.get('loop') || index) ? "show" : "hide"]().html(settings.get('previous')); - + slideshow(); - + // Preloads images within a rel group if (settings.get('preloading')) { $.each([getIndex(-1), getIndex(1)], function(){ @@ -835,32 +865,23 @@ } else { $groupControls.hide(); } - + if (settings.get('iframe')) { - iframe = document.createElement('iframe'); - - if ('frameBorder' in iframe) { - iframe.frameBorder = 0; - } - - if ('allowTransparency' in iframe) { - iframe.allowTransparency = "true"; - } + + iframe = settings.get('createIframe'); if (!settings.get('scrolling')) { iframe.scrolling = "no"; } - + $(iframe) .attr({ src: settings.get('href'), - name: (new Date()).getTime(), // give the iframe a unique name to prevent caching - 'class': prefix + 'Iframe', - allowFullScreen : true // allow HTML5 video to go fullscreen + 'class': prefix + 'Iframe' }) .one('load', complete) .appendTo($loaded); - + $events.one(event_purge, function () { iframe.src = "//about:blank"; }); @@ -871,14 +892,14 @@ } else { complete(); } - + if (settings.get('transition') === 'fade') { $box.fadeTo(speed, 1, removeFilter); } else { removeFilter(); } }; - + if (settings.get('transition') === 'fade') { $box.fadeTo(speed, 0, function () { publicMethod.position(0, callback); @@ -890,27 +911,27 @@ function load () { var href, setResize, prep = publicMethod.prep, $inline, request = ++requests; - + active = true; - + photo = false; - + trigger(event_purge); trigger(event_load); settings.get('onLoad'); - + settings.h = settings.get('height') ? setSize(settings.get('height'), 'y') - loadedHeight - interfaceHeight : settings.get('innerHeight') && setSize(settings.get('innerHeight'), 'y'); - + settings.w = settings.get('width') ? setSize(settings.get('width'), 'x') - loadedWidth - interfaceWidth : settings.get('innerWidth') && setSize(settings.get('innerWidth'), 'x'); - + // Sets the minimum dimensions for use in image scaling settings.mw = settings.w; settings.mh = settings.h; - + // Re-evaluate the minimum width and height based on maxWidth and maxHeight values. // If the width or height exceed the maxWidth or maxHeight, use the maximum values instead. if (settings.get('maxWidth')) { @@ -921,13 +942,13 @@ settings.mh = setSize(settings.get('maxHeight'), 'y') - loadedHeight - interfaceHeight; settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh; } - + href = settings.get('href'); - + loadingTimer = setTimeout(function () { $loadingOverlay.show(); }, 100); - + if (settings.get('inline')) { var $target = $(href); // Inserts an empty placeholder where inline content is being pulled from. @@ -949,11 +970,11 @@ href = retinaUrl(settings, href); - photo = new Image(); + photo = settings.get('createImg'); $(photo) .addClass(prefix + 'Photo') - .bind('error',function () { + .bind('error.'+prefix,function () { prep($tag(div, 'Error').html(settings.get('imgError'))); }) .one('load', function () { @@ -961,18 +982,11 @@ return; } - // A small pause because some browsers will occassionaly report a + // A small pause because some browsers will occassionaly report a // img.width and img.height of zero immediately after the img.onload fires setTimeout(function(){ var percent; - $.each(['alt', 'longdesc', 'aria-describedby'], function(i,val){ - var attr = $(settings.el).attr(val) || $(settings.el).attr('data-'+val); - if (attr) { - photo.setAttribute(val, attr); - } - }); - if (settings.get('retinaImage') && window.devicePixelRatio > 1) { photo.height = photo.height / window.devicePixelRatio; photo.width = photo.width / window.devicePixelRatio; @@ -992,16 +1006,17 @@ setResize(); } } - + if (settings.h) { photo.style.marginTop = Math.max(settings.mh - photo.height, 0) / 2 + 'px'; } - + if ($related[1] && (settings.get('loop') || $related[index + 1])) { photo.style.cursor = 'pointer'; - photo.onclick = function () { + + $(photo).bind('click.'+prefix, function () { publicMethod.next(); - }; + }); } photo.style.width = photo.width + 'px'; @@ -1009,7 +1024,7 @@ prep(photo); }, 1); }); - + photo.src = href; } else if (href) { @@ -1020,7 +1035,7 @@ }); } } - + // Navigates to the next page/image in a set. publicMethod.next = function () { if (!active && $related[1] && (settings.get('loop') || $related[index + 1])) { @@ -1028,7 +1043,7 @@ launch($related[index]); } }; - + publicMethod.prev = function () { if (!active && $related[1] && (settings.get('loop') || index)) { index = getIndex(-1); @@ -1039,20 +1054,20 @@ // Note: to use this within an iframe use the following format: parent.jQuery.colorbox.close(); publicMethod.close = function () { if (open && !closing) { - + closing = true; open = false; trigger(event_cleanup); settings.get('onCleanup'); $window.unbind('.' + prefix); $overlay.fadeTo(settings.get('fadeOut') || 0, 0); - + $box.stop().fadeTo(settings.get('fadeOut') || 0, 0, function () { $box.hide(); $overlay.hide(); trigger(event_purge); $loaded.remove(); - + setTimeout(function () { closing = false; trigger(event_closed); diff --git a/bower_components/jquery-colorbox/package.json b/bower_components/jquery-colorbox/package.json new file mode 100644 index 0000000..d94cb32 --- /dev/null +++ b/bower_components/jquery-colorbox/package.json @@ -0,0 +1,29 @@ +{ + "name": "jquery-colorbox", + "description": "jQuery lightbox and modal window plugin.", + "version": "1.6.1", + "keywords": [ + "modal", + "lightbox", + "gallery", + "popup", + "ui", + "jquery-plugin" + ], + "author": { + "name": "Jack Moore", + "url": "http://www.jacklmoore.com", + "email": "hello@jacklmoore.com" + }, + "main": "jquery.colorbox.js", + "license": "MIT", + "homepage": "http://www.jacklmoore.com/colorbox", + "demo": "http://www.jacklmoore.com/colorbox", + "repository": { + "type": "git", + "url": "http://github.com/jackmoore/colorbox.git" + }, + "dependencies": { + "jquery": ">=1.3.2" + } +} diff --git a/bower_components/jquery/.bower.json b/bower_components/jquery/.bower.json index fb1a0fc..51e22d3 100644 --- a/bower_components/jquery/.bower.json +++ b/bower_components/jquery/.bower.json @@ -1,11 +1,12 @@ { "name": "jquery", - "version": "1.11.1", + "version": "1.11.3", "main": "dist/jquery.js", "license": "MIT", "ignore": [ "**/.*", "build", + "dist/cdn", "speed", "test", "*.md", @@ -14,7 +15,7 @@ "package.json" ], "devDependencies": { - "sizzle": "1.10.19", + "sizzle": "2.1.1-jquery.2.1.2", "requirejs": "2.1.10", "qunit": "1.14.0", "sinon": "1.8.1" @@ -25,11 +26,11 @@ "library" ], "homepage": "https://github.com/jquery/jquery", - "_release": "1.11.1", + "_release": "1.11.3", "_resolution": { "type": "version", - "tag": "1.11.1", - "commit": "0d5ec2d8ac94a419ee47a39319c43ff9a7326b50" + "tag": "1.11.3", + "commit": "1472290917f17af05e98007136096784f9051fab" }, "_source": "git://github.com/jquery/jquery.git", "_target": "<2.0.0", diff --git a/bower_components/jquery/bower.json b/bower_components/jquery/bower.json index 03fad08..5a7561c 100644 --- a/bower_components/jquery/bower.json +++ b/bower_components/jquery/bower.json @@ -1,11 +1,12 @@ { "name": "jquery", - "version": "1.11.1", + "version": "1.11.3", "main": "dist/jquery.js", "license": "MIT", "ignore": [ "**/.*", "build", + "dist/cdn", "speed", "test", "*.md", @@ -14,7 +15,7 @@ "package.json" ], "devDependencies": { - "sizzle": "1.10.19", + "sizzle": "2.1.1-jquery.2.1.2", "requirejs": "2.1.10", "qunit": "1.14.0", "sinon": "1.8.1" diff --git a/bower_components/jquery/dist/jquery.js b/bower_components/jquery/dist/jquery.js index d4b67f7..6feb110 100644 --- a/bower_components/jquery/dist/jquery.js +++ b/bower_components/jquery/dist/jquery.js @@ -1,5 +1,5 @@ /*! - * jQuery JavaScript Library v1.11.1 + * jQuery JavaScript Library v1.11.3 * http://jquery.com/ * * Includes Sizzle.js @@ -9,7 +9,7 @@ * Released under the MIT license * http://jquery.org/license * - * Date: 2014-05-01T17:42Z + * Date: 2015-04-28T16:19Z */ (function( global, factory ) { @@ -64,7 +64,7 @@ var support = {}; var - version = "1.11.1", + version = "1.11.3", // Define a local copy of jQuery jQuery = function( selector, context ) { @@ -269,7 +269,8 @@ jQuery.extend({ // parseFloat NaNs numeric-cast false positives (null|true|false|"") // ...but misinterprets leading-number strings, particularly hex literals ("0x...") // subtraction forces infinities to NaN - return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0; + // adding 1 corrects loss of precision from parseFloat (#15100) + return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0; }, isEmptyObject: function( obj ) { @@ -568,7 +569,12 @@ jQuery.each("Boolean Number String Function Array Date RegExp Object Error".spli }); function isArraylike( obj ) { - var length = obj.length, + + // Support: iOS 8.2 (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = "length" in obj && obj.length, type = jQuery.type( obj ); if ( type === "function" || jQuery.isWindow( obj ) ) { @@ -584,14 +590,14 @@ function isArraylike( obj ) { } var Sizzle = /*! - * Sizzle CSS Selector Engine v1.10.19 + * Sizzle CSS Selector Engine v2.2.0-pre * http://sizzlejs.com/ * - * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors * Released under the MIT license * http://jquery.org/license * - * Date: 2014-04-18 + * Date: 2014-12-16 */ (function( window ) { @@ -618,7 +624,7 @@ var i, contains, // Instance-specific data - expando = "sizzle" + -(new Date()), + expando = "sizzle" + 1 * new Date(), preferredDoc = window.document, dirruns = 0, done = 0, @@ -633,7 +639,6 @@ var i, }, // General-purpose constants - strundefined = typeof undefined, MAX_NEGATIVE = 1 << 31, // Instance methods @@ -643,12 +648,13 @@ var i, push_native = arr.push, push = arr.push, slice = arr.slice, - // Use a stripped-down indexOf if we can't use a native one - indexOf = arr.indexOf || function( elem ) { + // Use a stripped-down indexOf as it's faster than native + // http://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { var i = 0, - len = this.length; + len = list.length; for ( ; i < len; i++ ) { - if ( this[i] === elem ) { + if ( list[i] === elem ) { return i; } } @@ -688,6 +694,7 @@ var i, ")\\)|)", // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), @@ -739,6 +746,14 @@ var i, String.fromCharCode( high + 0x10000 ) : // Supplemental Plane codepoint (surrogate pair) String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); }; // Optimize for push.apply( _, NodeList ) @@ -781,19 +796,18 @@ function Sizzle( selector, context, results, seed ) { context = context || document; results = results || []; + nodeType = context.nodeType; - if ( !selector || typeof selector !== "string" ) { - return results; - } + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { - return []; + return results; } - if ( documentIsHTML && !seed ) { + if ( !seed && documentIsHTML ) { - // Shortcuts - if ( (match = rquickExpr.exec( selector )) ) { + // Try to shortcut find operations when possible (e.g., not under DocumentFragment) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { // Speed-up: Sizzle("#ID") if ( (m = match[1]) ) { if ( nodeType === 9 ) { @@ -825,7 +839,7 @@ function Sizzle( selector, context, results, seed ) { return results; // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + } else if ( (m = match[3]) && support.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); return results; } @@ -835,7 +849,7 @@ function Sizzle( selector, context, results, seed ) { if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { nid = old = expando; newContext = context; - newSelector = nodeType === 9 && selector; + newSelector = nodeType !== 1 && selector; // qSA works strangely on Element-rooted queries // We can work around this by specifying an extra ID on the root @@ -1022,7 +1036,7 @@ function createPositionalPseudo( fn ) { * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value */ function testContext( context ) { - return context && typeof context.getElementsByTagName !== strundefined && context; + return context && typeof context.getElementsByTagName !== "undefined" && context; } // Expose support vars for convenience @@ -1046,9 +1060,8 @@ isXML = Sizzle.isXML = function( elem ) { * @returns {Object} Returns the current document */ setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, - doc = node ? node.ownerDocument || node : preferredDoc, - parent = doc.defaultView; + var hasCompare, parent, + doc = node ? node.ownerDocument || node : preferredDoc; // If no document and documentElement is available, return if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { @@ -1058,9 +1071,7 @@ setDocument = Sizzle.setDocument = function( node ) { // Set our document document = doc; docElem = doc.documentElement; - - // Support tests - documentIsHTML = !isXML( doc ); + parent = doc.defaultView; // Support: IE>8 // If iframe document is assigned to "document" variable and if iframe has been reloaded, @@ -1069,21 +1080,22 @@ setDocument = Sizzle.setDocument = function( node ) { if ( parent && parent !== parent.top ) { // IE11 does not have attachEvent, so all must suffer if ( parent.addEventListener ) { - parent.addEventListener( "unload", function() { - setDocument(); - }, false ); + parent.addEventListener( "unload", unloadHandler, false ); } else if ( parent.attachEvent ) { - parent.attachEvent( "onunload", function() { - setDocument(); - }); + parent.attachEvent( "onunload", unloadHandler ); } } + /* Support tests + ---------------------------------------------------------------------- */ + documentIsHTML = !isXML( doc ); + /* Attributes ---------------------------------------------------------------------- */ // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) support.attributes = assert(function( div ) { div.className = "i"; return !div.getAttribute("className"); @@ -1098,17 +1110,8 @@ setDocument = Sizzle.setDocument = function( node ) { return !div.getElementsByTagName("*").length; }); - // Check if getElementsByClassName can be trusted - support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) { - div.innerHTML = "<div class='a'></div><div class='a i'></div>"; - - // Support: Safari<4 - // Catch class over-caching - div.firstChild.className = "i"; - // Support: Opera<10 - // Catch gEBCN failure to find non-leading classes - return div.getElementsByClassName("i").length === 2; - }); + // Support: IE<9 + support.getElementsByClassName = rnative.test( doc.getElementsByClassName ); // Support: IE<10 // Check if getElementById returns elements by name @@ -1122,7 +1125,7 @@ setDocument = Sizzle.setDocument = function( node ) { // ID find and filter if ( support.getById ) { Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { var m = context.getElementById( id ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 @@ -1143,7 +1146,7 @@ setDocument = Sizzle.setDocument = function( node ) { Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return node && node.value === attrId; }; }; @@ -1152,14 +1155,20 @@ setDocument = Sizzle.setDocument = function( node ) { // Tag Expr.find["TAG"] = support.getElementsByTagName ? function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); } } : + function( tag, context ) { var elem, tmp = [], i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too results = context.getElementsByTagName( tag ); // Filter out possible comments @@ -1177,7 +1186,7 @@ setDocument = Sizzle.setDocument = function( node ) { // Class Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + if ( documentIsHTML ) { return context.getElementsByClassName( className ); } }; @@ -1206,13 +1215,15 @@ setDocument = Sizzle.setDocument = function( node ) { // setting a boolean content attribute, // since its presence should be enough // http://bugs.jquery.com/ticket/12359 - div.innerHTML = "<select msallowclip=''><option selected=''></option></select>"; + docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" + + "<select id='" + expando + "-\f]' msallowcapture=''>" + + "<option selected=''></option></select>"; // Support: IE8, Opera 11-12.16 // Nothing should be selected when empty strings follow ^= or $= or *= // The test attribute must be unknown in Opera but "safe" for WinRT // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( div.querySelectorAll("[msallowclip^='']").length ) { + if ( div.querySelectorAll("[msallowcapture^='']").length ) { rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); } @@ -1222,12 +1233,24 @@ setDocument = Sizzle.setDocument = function( node ) { rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); } + // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+ + if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + // Webkit/Opera - :checked should return selected option elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked // IE8 throws error here and will not see later tests if ( !div.querySelectorAll(":checked").length ) { rbuggyQSA.push(":checked"); } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibing-combinator selector` fails + if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } }); assert(function( div ) { @@ -1344,7 +1367,7 @@ setDocument = Sizzle.setDocument = function( node ) { // Maintain original order return sortInput ? - ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 0; } @@ -1371,7 +1394,7 @@ setDocument = Sizzle.setDocument = function( node ) { aup ? -1 : bup ? 1 : sortInput ? - ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 0; // If the nodes are siblings, we can do a quick check @@ -1434,7 +1457,7 @@ Sizzle.matchesSelector = function( elem, expr ) { elem.document && elem.document.nodeType !== 11 ) { return ret; } - } catch(e) {} + } catch (e) {} } return Sizzle( expr, document, null, [ elem ] ).length > 0; @@ -1653,7 +1676,7 @@ Expr = Sizzle.selectors = { return pattern || (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); }); }, @@ -1675,7 +1698,7 @@ Expr = Sizzle.selectors = { operator === "^=" ? check && result.indexOf( check ) === 0 : operator === "*=" ? check && result.indexOf( check ) > -1 : operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : false; }; @@ -1795,7 +1818,7 @@ Expr = Sizzle.selectors = { matched = fn( seed, argument ), i = matched.length; while ( i-- ) { - idx = indexOf.call( seed, matched[i] ); + idx = indexOf( seed, matched[i] ); seed[ idx ] = !( matches[ idx ] = matched[i] ); } }) : @@ -1834,6 +1857,8 @@ Expr = Sizzle.selectors = { function( elem, context, xml ) { input[0] = elem; matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; return !results.pop(); }; }), @@ -1845,6 +1870,7 @@ Expr = Sizzle.selectors = { }), "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); return function( elem ) { return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; }; @@ -2266,7 +2292,7 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS i = matcherOut.length; while ( i-- ) { if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { seed[temp] = !(results[temp] = elem); } @@ -2301,13 +2327,16 @@ function matcherFromTokens( tokens ) { return elem === checkContext; }, implicitRelative, true ), matchAnyContext = addCombinator( function( elem ) { - return indexOf.call( checkContext, elem ) > -1; + return indexOf( checkContext, elem ) > -1; }, implicitRelative, true ), matchers = [ function( elem, context, xml ) { - return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( (checkContext = context).nodeType ? matchContext( elem, context, xml ) : matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; } ]; for ( ; i < len; i++ ) { @@ -2557,7 +2586,7 @@ select = Sizzle.select = function( selector, context, results, seed ) { // Sort stability support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; -// Support: Chrome<14 +// Support: Chrome 14-35+ // Always assume duplicates if they aren't passed to the comparison function support.detectDuplicates = !!hasDuplicate; @@ -6115,7 +6144,14 @@ var getStyles, curCSS, if ( window.getComputedStyle ) { getStyles = function( elem ) { - return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); + // Support: IE<=11+, Firefox<=30+ (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + if ( elem.ownerDocument.defaultView.opener ) { + return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); + } + + return window.getComputedStyle( elem, null ); }; curCSS = function( elem, name, computed ) { @@ -6363,6 +6399,8 @@ function addGetHookIf( conditionFn, hookFn ) { reliableMarginRightVal = !parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight ); + + div.removeChild( contents ); } // Support: IE8 @@ -9070,7 +9108,8 @@ jQuery.extend({ } // We can fire global events as of now if asked to - fireGlobals = s.global; + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; // Watch for a new set of requests if ( fireGlobals && jQuery.active++ === 0 ) { @@ -9329,13 +9368,6 @@ jQuery.each( [ "get", "post" ], function( i, method ) { }; }); -// Attach a bunch of functions for handling common AJAX events -jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) { - jQuery.fn[ type ] = function( fn ) { - return this.on( type, fn ); - }; -}); - jQuery._evalUrl = function( url ) { return jQuery.ajax({ @@ -9561,8 +9593,9 @@ var xhrId = 0, // Support: IE<10 // Open requests must be manually aborted on unload (#5280) -if ( window.ActiveXObject ) { - jQuery( window ).on( "unload", function() { +// See https://support.microsoft.com/kb/2856746 for more info +if ( window.attachEvent ) { + window.attachEvent( "onunload", function() { for ( var key in xhrCallbacks ) { xhrCallbacks[ key ]( undefined, true ); } @@ -9996,6 +10029,16 @@ jQuery.fn.load = function( url, params, callback ) { +// Attach a bunch of functions for handling common AJAX events +jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) { + jQuery.fn[ type ] = function( fn ) { + return this.on( type, fn ); + }; +}); + + + + jQuery.expr.filters.animated = function( elem ) { return jQuery.grep(jQuery.timers, function( fn ) { return elem === fn.elem; diff --git a/bower_components/jquery/src/ajax.js b/bower_components/jquery/src/ajax.js index 1b01fd6..8a1b8b6 100644 --- a/bower_components/jquery/src/ajax.js +++ b/bower_components/jquery/src/ajax.js @@ -537,7 +537,8 @@ jQuery.extend({ } // We can fire global events as of now if asked to - fireGlobals = s.global; + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; // Watch for a new set of requests if ( fireGlobals && jQuery.active++ === 0 ) { @@ -796,12 +797,5 @@ jQuery.each( [ "get", "post" ], function( i, method ) { }; }); -// Attach a bunch of functions for handling common AJAX events -jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) { - jQuery.fn[ type ] = function( fn ) { - return this.on( type, fn ); - }; -}); - return jQuery; }); diff --git a/bower_components/jquery/src/ajax/xhr.js b/bower_components/jquery/src/ajax/xhr.js index 0f560f4..f458ceb 100644 --- a/bower_components/jquery/src/ajax/xhr.js +++ b/bower_components/jquery/src/ajax/xhr.js @@ -32,8 +32,9 @@ var xhrId = 0, // Support: IE<10 // Open requests must be manually aborted on unload (#5280) -if ( window.ActiveXObject ) { - jQuery( window ).on( "unload", function() { +// See https://support.microsoft.com/kb/2856746 for more info +if ( window.attachEvent ) { + window.attachEvent( "onunload", function() { for ( var key in xhrCallbacks ) { xhrCallbacks[ key ]( undefined, true ); } diff --git a/bower_components/jquery/src/core.js b/bower_components/jquery/src/core.js index d350104..7c9c72c 100644 --- a/bower_components/jquery/src/core.js +++ b/bower_components/jquery/src/core.js @@ -216,7 +216,8 @@ jQuery.extend({ // parseFloat NaNs numeric-cast false positives (null|true|false|"") // ...but misinterprets leading-number strings, particularly hex literals ("0x...") // subtraction forces infinities to NaN - return !jQuery.isArray( obj ) && obj - parseFloat( obj ) >= 0; + // adding 1 corrects loss of precision from parseFloat (#15100) + return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0; }, isEmptyObject: function( obj ) { @@ -515,7 +516,12 @@ jQuery.each("Boolean Number String Function Array Date RegExp Object Error".spli }); function isArraylike( obj ) { - var length = obj.length, + + // Support: iOS 8.2 (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = "length" in obj && obj.length, type = jQuery.type( obj ); if ( type === "function" || jQuery.isWindow( obj ) ) { diff --git a/bower_components/jquery/src/css/curCSS.js b/bower_components/jquery/src/css/curCSS.js index 1f3b734..9ab4f11 100644 --- a/bower_components/jquery/src/css/curCSS.js +++ b/bower_components/jquery/src/css/curCSS.js @@ -11,7 +11,14 @@ var getStyles, curCSS, if ( window.getComputedStyle ) { getStyles = function( elem ) { - return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); + // Support: IE<=11+, Firefox<=30+ (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + if ( elem.ownerDocument.defaultView.opener ) { + return elem.ownerDocument.defaultView.getComputedStyle( elem, null ); + } + + return window.getComputedStyle( elem, null ); }; curCSS = function( elem, name, computed ) { diff --git a/bower_components/jquery/src/css/support.js b/bower_components/jquery/src/css/support.js index 4a8fc87..05f5cc8 100644 --- a/bower_components/jquery/src/css/support.js +++ b/bower_components/jquery/src/css/support.js @@ -120,6 +120,8 @@ define([ reliableMarginRightVal = !parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight ); + + div.removeChild( contents ); } // Support: IE8 diff --git a/bower_components/jquery/src/event/ajax.js b/bower_components/jquery/src/event/ajax.js new file mode 100644 index 0000000..278c403 --- /dev/null +++ b/bower_components/jquery/src/event/ajax.js @@ -0,0 +1,13 @@ +define([ + "../core", + "../event" +], function( jQuery ) { + +// Attach a bunch of functions for handling common AJAX events +jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) { + jQuery.fn[ type ] = function( fn ) { + return this.on( type, fn ); + }; +}); + +}); diff --git a/bower_components/jquery/src/jquery.js b/bower_components/jquery/src/jquery.js index ac5ea9f..7c1528b 100644 --- a/bower_components/jquery/src/jquery.js +++ b/bower_components/jquery/src/jquery.js @@ -23,6 +23,7 @@ define([ "./ajax/script", "./ajax/jsonp", "./ajax/load", + "./event/ajax", "./effects", "./effects/animatedSelector", "./offset", diff --git a/bower_components/jquery/src/sizzle/dist/sizzle.js b/bower_components/jquery/src/sizzle/dist/sizzle.js index 20bc017..89aecbc 100644 --- a/bower_components/jquery/src/sizzle/dist/sizzle.js +++ b/bower_components/jquery/src/sizzle/dist/sizzle.js @@ -1,12 +1,12 @@ /*! - * Sizzle CSS Selector Engine v1.10.19 + * Sizzle CSS Selector Engine v2.2.0-pre * http://sizzlejs.com/ * - * Copyright 2013 jQuery Foundation, Inc. and other contributors + * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors * Released under the MIT license * http://jquery.org/license * - * Date: 2014-04-18 + * Date: 2014-12-16 */ (function( window ) { @@ -33,7 +33,7 @@ var i, contains, // Instance-specific data - expando = "sizzle" + -(new Date()), + expando = "sizzle" + 1 * new Date(), preferredDoc = window.document, dirruns = 0, done = 0, @@ -48,7 +48,6 @@ var i, }, // General-purpose constants - strundefined = typeof undefined, MAX_NEGATIVE = 1 << 31, // Instance methods @@ -58,12 +57,13 @@ var i, push_native = arr.push, push = arr.push, slice = arr.slice, - // Use a stripped-down indexOf if we can't use a native one - indexOf = arr.indexOf || function( elem ) { + // Use a stripped-down indexOf as it's faster than native + // http://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { var i = 0, - len = this.length; + len = list.length; for ( ; i < len; i++ ) { - if ( this[i] === elem ) { + if ( list[i] === elem ) { return i; } } @@ -103,6 +103,7 @@ var i, ")\\)|)", // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), @@ -154,6 +155,14 @@ var i, String.fromCharCode( high + 0x10000 ) : // Supplemental Plane codepoint (surrogate pair) String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); }; // Optimize for push.apply( _, NodeList ) @@ -196,19 +205,18 @@ function Sizzle( selector, context, results, seed ) { context = context || document; results = results || []; + nodeType = context.nodeType; - if ( !selector || typeof selector !== "string" ) { - return results; - } + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { - if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { - return []; + return results; } - if ( documentIsHTML && !seed ) { + if ( !seed && documentIsHTML ) { - // Shortcuts - if ( (match = rquickExpr.exec( selector )) ) { + // Try to shortcut find operations when possible (e.g., not under DocumentFragment) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { // Speed-up: Sizzle("#ID") if ( (m = match[1]) ) { if ( nodeType === 9 ) { @@ -240,7 +248,7 @@ function Sizzle( selector, context, results, seed ) { return results; // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) { + } else if ( (m = match[3]) && support.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); return results; } @@ -250,7 +258,7 @@ function Sizzle( selector, context, results, seed ) { if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { nid = old = expando; newContext = context; - newSelector = nodeType === 9 && selector; + newSelector = nodeType !== 1 && selector; // qSA works strangely on Element-rooted queries // We can work around this by specifying an extra ID on the root @@ -437,7 +445,7 @@ function createPositionalPseudo( fn ) { * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value */ function testContext( context ) { - return context && typeof context.getElementsByTagName !== strundefined && context; + return context && typeof context.getElementsByTagName !== "undefined" && context; } // Expose support vars for convenience @@ -461,9 +469,8 @@ isXML = Sizzle.isXML = function( elem ) { * @returns {Object} Returns the current document */ setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, - doc = node ? node.ownerDocument || node : preferredDoc, - parent = doc.defaultView; + var hasCompare, parent, + doc = node ? node.ownerDocument || node : preferredDoc; // If no document and documentElement is available, return if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { @@ -473,9 +480,7 @@ setDocument = Sizzle.setDocument = function( node ) { // Set our document document = doc; docElem = doc.documentElement; - - // Support tests - documentIsHTML = !isXML( doc ); + parent = doc.defaultView; // Support: IE>8 // If iframe document is assigned to "document" variable and if iframe has been reloaded, @@ -484,21 +489,22 @@ setDocument = Sizzle.setDocument = function( node ) { if ( parent && parent !== parent.top ) { // IE11 does not have attachEvent, so all must suffer if ( parent.addEventListener ) { - parent.addEventListener( "unload", function() { - setDocument(); - }, false ); + parent.addEventListener( "unload", unloadHandler, false ); } else if ( parent.attachEvent ) { - parent.attachEvent( "onunload", function() { - setDocument(); - }); + parent.attachEvent( "onunload", unloadHandler ); } } + /* Support tests + ---------------------------------------------------------------------- */ + documentIsHTML = !isXML( doc ); + /* Attributes ---------------------------------------------------------------------- */ // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans) + // Verify that getAttribute really returns attributes and not properties + // (excepting IE8 booleans) support.attributes = assert(function( div ) { div.className = "i"; return !div.getAttribute("className"); @@ -513,17 +519,8 @@ setDocument = Sizzle.setDocument = function( node ) { return !div.getElementsByTagName("*").length; }); - // Check if getElementsByClassName can be trusted - support.getElementsByClassName = rnative.test( doc.getElementsByClassName ) && assert(function( div ) { - div.innerHTML = "<div class='a'></div><div class='a i'></div>"; - - // Support: Safari<4 - // Catch class over-caching - div.firstChild.className = "i"; - // Support: Opera<10 - // Catch gEBCN failure to find non-leading classes - return div.getElementsByClassName("i").length === 2; - }); + // Support: IE<9 + support.getElementsByClassName = rnative.test( doc.getElementsByClassName ); // Support: IE<10 // Check if getElementById returns elements by name @@ -537,7 +534,7 @@ setDocument = Sizzle.setDocument = function( node ) { // ID find and filter if ( support.getById ) { Expr.find["ID"] = function( id, context ) { - if ( typeof context.getElementById !== strundefined && documentIsHTML ) { + if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { var m = context.getElementById( id ); // Check parentNode to catch when Blackberry 4.6 returns // nodes that are no longer in the document #6963 @@ -558,7 +555,7 @@ setDocument = Sizzle.setDocument = function( node ) { Expr.filter["ID"] = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id"); return node && node.value === attrId; }; }; @@ -567,14 +564,20 @@ setDocument = Sizzle.setDocument = function( node ) { // Tag Expr.find["TAG"] = support.getElementsByTagName ? function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { return context.getElementsByTagName( tag ); + + // DocumentFragment nodes don't have gEBTN + } else if ( support.qsa ) { + return context.querySelectorAll( tag ); } } : + function( tag, context ) { var elem, tmp = [], i = 0, + // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too results = context.getElementsByTagName( tag ); // Filter out possible comments @@ -592,7 +595,7 @@ setDocument = Sizzle.setDocument = function( node ) { // Class Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) { - if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) { + if ( documentIsHTML ) { return context.getElementsByClassName( className ); } }; @@ -621,13 +624,15 @@ setDocument = Sizzle.setDocument = function( node ) { // setting a boolean content attribute, // since its presence should be enough // http://bugs.jquery.com/ticket/12359 - div.innerHTML = "<select msallowclip=''><option selected=''></option></select>"; + docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" + + "<select id='" + expando + "-\f]' msallowcapture=''>" + + "<option selected=''></option></select>"; // Support: IE8, Opera 11-12.16 // Nothing should be selected when empty strings follow ^= or $= or *= // The test attribute must be unknown in Opera but "safe" for WinRT // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( div.querySelectorAll("[msallowclip^='']").length ) { + if ( div.querySelectorAll("[msallowcapture^='']").length ) { rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); } @@ -637,12 +642,24 @@ setDocument = Sizzle.setDocument = function( node ) { rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); } + // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+ + if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push("~="); + } + // Webkit/Opera - :checked should return selected option elements // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked // IE8 throws error here and will not see later tests if ( !div.querySelectorAll(":checked").length ) { rbuggyQSA.push(":checked"); } + + // Support: Safari 8+, iOS 8+ + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibing-combinator selector` fails + if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push(".#.+[+~]"); + } }); assert(function( div ) { @@ -759,7 +776,7 @@ setDocument = Sizzle.setDocument = function( node ) { // Maintain original order return sortInput ? - ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 0; } @@ -786,7 +803,7 @@ setDocument = Sizzle.setDocument = function( node ) { aup ? -1 : bup ? 1 : sortInput ? - ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : + ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : 0; // If the nodes are siblings, we can do a quick check @@ -849,7 +866,7 @@ Sizzle.matchesSelector = function( elem, expr ) { elem.document && elem.document.nodeType !== 11 ) { return ret; } - } catch(e) {} + } catch (e) {} } return Sizzle( expr, document, null, [ elem ] ).length > 0; @@ -1068,7 +1085,7 @@ Expr = Sizzle.selectors = { return pattern || (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && classCache( className, function( elem ) { - return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" ); + return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" ); }); }, @@ -1090,7 +1107,7 @@ Expr = Sizzle.selectors = { operator === "^=" ? check && result.indexOf( check ) === 0 : operator === "*=" ? check && result.indexOf( check ) > -1 : operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : + operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : false; }; @@ -1210,7 +1227,7 @@ Expr = Sizzle.selectors = { matched = fn( seed, argument ), i = matched.length; while ( i-- ) { - idx = indexOf.call( seed, matched[i] ); + idx = indexOf( seed, matched[i] ); seed[ idx ] = !( matches[ idx ] = matched[i] ); } }) : @@ -1249,6 +1266,8 @@ Expr = Sizzle.selectors = { function( elem, context, xml ) { input[0] = elem; matcher( input, null, xml, results ); + // Don't keep the element (issue #299) + input[0] = null; return !results.pop(); }; }), @@ -1260,6 +1279,7 @@ Expr = Sizzle.selectors = { }), "contains": markFunction(function( text ) { + text = text.replace( runescape, funescape ); return function( elem ) { return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; }; @@ -1681,7 +1701,7 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS i = matcherOut.length; while ( i-- ) { if ( (elem = matcherOut[i]) && - (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) { + (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) { seed[temp] = !(results[temp] = elem); } @@ -1716,13 +1736,16 @@ function matcherFromTokens( tokens ) { return elem === checkContext; }, implicitRelative, true ), matchAnyContext = addCombinator( function( elem ) { - return indexOf.call( checkContext, elem ) > -1; + return indexOf( checkContext, elem ) > -1; }, implicitRelative, true ), matchers = [ function( elem, context, xml ) { - return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( (checkContext = context).nodeType ? matchContext( elem, context, xml ) : matchAnyContext( elem, context, xml ) ); + // Avoid hanging onto element (issue #299) + checkContext = null; + return ret; } ]; for ( ; i < len; i++ ) { @@ -1972,7 +1995,7 @@ select = Sizzle.select = function( selector, context, results, seed ) { // Sort stability support.sortStable = expando.split("").sort( sortOrder ).join("") === expando; -// Support: Chrome<14 +// Support: Chrome 14-35+ // Always assume duplicates if they aren't passed to the comparison function support.detectDuplicates = !!hasDuplicate; diff --git a/bower_components/jquery/src/wrap.js b/bower_components/jquery/src/wrap.js index a3c35d9..93c7b2c 100644 --- a/bower_components/jquery/src/wrap.js +++ b/bower_components/jquery/src/wrap.js @@ -1,6 +1,7 @@ define([ "./core", "./core/init", + "./manipulation", // clone "./traversing" // parent, contents ], function( jQuery ) { diff --git a/bower_components/livereload-js/.bower.json b/bower_components/livereload-js/.bower.json new file mode 100644 index 0000000..3a1656a --- /dev/null +++ b/bower_components/livereload-js/.bower.json @@ -0,0 +1,40 @@ +{ + "name": "livereload-js", + "version": "2.2.1", + "main": "dist/livereload.js", + "homepage": "http://livereload.com", + "authors": [ + "Andrey Tarantsov <andrey@tarantsov.com>", + "David Kelso <david@kelso.id.au>" + ], + "description": "LiveReload JS client - auto reload browser on changes", + "keywords": [ + "javascript", + "livereload" + ], + "license": "MIT", + "ignore": [ + "Rakefile", + "lib", + "lib-cov", + "src", + "test", + "**/.*", + "node_modules", + "bower_components", + "tests" + ], + "moduleType": [ + "globals" + ], + "_release": "2.2.1", + "_resolution": { + "type": "version", + "tag": "v2.2.1", + "commit": "91fdfa00a3e7fac0482397a315e18947c54bbfd3" + }, + "_source": "git://github.com/livereload/livereload-js.git", + "_target": "~2.2.1", + "_originalSource": "livereload-js", + "_direct": true +}
\ No newline at end of file diff --git a/bower_components/livereload-js/Gruntfile.js b/bower_components/livereload-js/Gruntfile.js new file mode 100644 index 0000000..1c417c3 --- /dev/null +++ b/bower_components/livereload-js/Gruntfile.js @@ -0,0 +1,42 @@ +module.exports = function(grunt) { + + grunt.initConfig({ + coffee: { + src: { + expand: true, + cwd: 'src', + src: '*.coffee', + dest: 'lib', + ext: '.js' + } + }, + + browserify: { + dist: { + options: { + + }, + src: ['lib/startup.js'], + dest: 'dist/livereload.js' + } + }, + + mochaTest: { + test: { + options: { + reporter: 'spec' + }, + src: ['test/*.js'] + } + } + }); + + grunt.loadNpmTasks('grunt-contrib-coffee'); + grunt.loadNpmTasks('grunt-browserify'); + grunt.loadNpmTasks('grunt-mocha-test'); + + grunt.registerTask('build', ['coffee', 'browserify']); + grunt.registerTask('test', ['mochaTest']); + grunt.registerTask('default', ['build', 'test']); + +}; diff --git a/bower_components/livereload-js/LICENSE b/bower_components/livereload-js/LICENSE new file mode 100644 index 0000000..c8aa29b --- /dev/null +++ b/bower_components/livereload-js/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2010-2012 Andrey Tarantsov + +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/bower_components/livereload-js/README.md b/bower_components/livereload-js/README.md new file mode 100644 index 0000000..96491b9 --- /dev/null +++ b/bower_components/livereload-js/README.md @@ -0,0 +1,220 @@ +LiveReload.js +============= + +What is LiveReload? +------------------- + +LiveReload is a tool for web developers and designers. See [livereload.com](http://livereload.com) for more info. + +To use LiveReload, you need a client (this script) in your browser and a server running on your development machine. + +This repository (livereload.js) implements the client side of the protocol. The client connects to a LiveReload server via web sockets and listens for incoming change notifications. When a CSS or an image file is modified, it is live-refreshed without reloading the page. When any other file is modified, the page is reloaded. + +The server notifies the client whenever a change is made. Available servers are: + +* [LiveReload app for Mac](http://livereload.com/) +* [rack-livereload](https://github.com/johnbintz/rack-livereload) +* [guard-livereload](https://github.com/guard/guard-livereload) +* [grunt-contrib-watch](https://github.com/gruntjs/grunt-contrib-watch) +* more available on Google :-) +* you can even write your own; refer to the [LiveReload protocol](http://help.livereload.com/kb/ecosystem/livereload-protocol) + +If you are a web developer looking to _use_ LiveReload, you should refer to your LiveReload server/app/tool's documentation, rather that this repository. **You should use the copy of livereload.js script bundled with your server**, because it's guaranteed to be compatible, and may be customized for that server. + +Most LiveReload server vendors will serve livereload.js on the LiveReload port. When your server is running, you can typically access the script at `http://0.0.0.0:35729/livereload.js`. + +Please read on *only* if you are: + +* using a server that doesn't document the usage of livereload.js +* interested in hacking on livereload.js or want to understand it better +* developing a LiveReload server + + +What is livereload.js? +---------------------- + +This repository contains a JavaScript file implementing the client side of the LiveReload protocol. It gets change notifications from a LiveReload server and applies them to the browser. + +If you are **developing** a LiveReload server, see [dist/livereload.js](https://github.com/livereload/livereload-js/raw/master/dist/livereload.js) for the latest version built using the sources in this repository. We require LiveReload server vendors to distribute livereload.js as part of their apps or tools. + +An old version of this script is also bundled with the LiveReload browser extensions, but it's not getting updated and only serves for compatibility with very old clients. + +Features: + +* Live CSS reloading +* Full page reloading +* Protocol, WebSocket communication +* CSS `@import` support +* Live image reloading (`<img src="..." />`, `background-image` and `border-image` properties, both inline and in stylesheets) +* Live, in-browser LESS.js reloading + +Would love, but doesn't seem possible: + +* live JS reloading + + +Installing using Bower and npm +------------------------------ + +This script is published on Bower and npm. (But, to reiterate: the preferred method is to avoid installing it altogether, and instead use the one bundled with your LiveReload server/app/tool.) + +Using Bower: + + bower install livereload-js --save-dev + +This gives you a component containing a single script file, `dist/livereload.js`. + +If you're using Browserify, you can require LiveReload via npm: + + npm install livereload-js --save + +Note that the package uses `window` and `document` globals, so won't run under Node.js environment. + + +Using livereload.js +------------------- + +This script is meant to be included into the web pages you want to monitor, like this: + + <script src="http://localhost:35729/livereload.js"></script> + +LiveReload 2 server listens on port `35729` and serves livereload.js over HTTP (besides speaking the web socket protocol on the same port). + +A slightly smarter way is to use the host name of the current page, assuming that it is being served from the same computer. This approach enables LiveReload when viewing the web page from other devices on the network: + +```html +<script>document.write('<script src="http://' + + location.host.split(':')[0] + + ':35729/livereload.js"></' + + 'script>')</script> +``` + + +However, since `location.host` is empty for `file:` URLs, we need to account for that: + +```html +<script>document.write('<script src="http://' + + (location.host || 'localhost').split(':')[0] + + ':35729/livereload.js"></' + + 'script>')</script> +``` + + +LiveReload.js finds a `script` tag that includes `…/livereload.js` and uses it to determine the hostname/port to connect to. It also understands some options from the query string: `host`, `port`, `snipver`, `mindelay` and `maxdelay`. + +`snipver` specifies a version of the snippet, so that we can warn when the snippet needs to be updated. The currently recommended `snipver` is version 1: + +```html +<script>document.write('<script src="http://' + + (location.host || 'localhost').split(':')[0] + + ':35729/livereload.js?snipver=1"></' + + 'script>')</script> +``` + + +Additionally, you might want to specify `mindelay` and `maxdelay`, which is minimum and maximum reconnection delay in milliseconds (defaulting to `1000` and `60000`). + +Alternatively, instead of loading livereload.js from the LiveReload server, you might want to include it from a different URL. In this case, add a `host` parameter to override the host name. For example: + +```html +<script src="https://github.com/livereload/livereload-js/raw/master/dist/livereload.js?host=localhost"></script> +``` + + +Issues & Limitations +-------------------- + +**Live reloading of imported stylesheets has a 200ms lag.** Modifying a CSS `@import` rule to reference a not-yet-cached file causes WebKit to lose all document styles, so we have to apply a workaround that causes a lag. + +Our workaround is to add a temporary `<link />` element for the imported stylesheet we're trying to reload, wait 200ms to make sure WebKit loads the new file, then remove `<link />` and recreate the `@import` rule. This prevents a flash of unstyled content. (We also wait 200 more milliseconds and recreate the `@import` rule again, in case those initial 200ms were not enough.) + +**Live image reloading is limited to `<img src="..." />`, `background-image` and `border-image` styles.** Any other places where images can be mentioned? + +**Live image reloading is limited to `jpg`, `jpeg`, `gif`, and `png` extensions.** Maybe need to add `svg` there? Anything else? + + +Communicating with livereload.js +-------------------------------- + +It is possible to communicate with a running LiveReload script using DOM events: + +* fire `LiveReloadShutDown` event on `document` to make LiveReload disconnect and go away +* listen for `LiveReloadConnect` event on `document` to learn when the connection is established +* listen for `LiveReloadDisconnect` event on `document` to learn when the connection is interrupted (or fails to be established) + +The `LiveReload` object is also exposed as `window.LiveReload`, with `LiveReload.disconnect()`, `LiveReload.connect()`, and `LiveReload.shutDown()` available. However, I'm not yet sure if I want to keep this API, so consider it non-contractual. (And please tell me if you have a use for it!) + + +Having trouble? +--------------- + +To enable debugging output to console, append `?LR-verbose` to your URL. + + +Hacking on LiveReload.js +------------------------ + +Requirements: + +* Node.js with npm +* Grunt (`npm install grunt-cli`) + +To install additional prerequisites: + + npm install + +To build: + + grunt build + +To run tests: + + grunt + + +Releasing a new version +----------------------- + +1. Update the version number in `package.json`. + +1. Run `rake version` to update the version numbers in all other files, using the one from `package.json`. + +1. Run `grunt`. + +1. Do some manual testing. + +1. Tag the version in Git: `rake tag` then `git push --tags`. + +1. `npm publish` + + +License +------- + +livereload-js is available under the MIT license. See the LICENSE file for details. + + +Version history +--------------- + +2.2.1 (Jan 17, 2015) + +* npm fix: actually include `/lib` in the package + +2.2.0 (Jan 16, 2015) + +* the first version stitched with Browserify; everything seems to work, but 2.1.0 is available just in case +* switched the build system to Grunt + +2.1.0 (Jan 16, 2015) + +* use case-insensitive matching for `rel` attribute in `<link rel="stylesheet">` tags, to accomodate legacy Rails versions +* avoid usage of `console` when it's not definited +* some README changes + +2.0.8 (May 22, 2012) + +* Fix live CSS refresh to work with prefixfree +* Correctly trigger removal of old `<link>` tags + +(older history not recorded) diff --git a/bower_components/livereload-js/bower.json b/bower_components/livereload-js/bower.json new file mode 100644 index 0000000..c715d6e --- /dev/null +++ b/bower_components/livereload-js/bower.json @@ -0,0 +1,30 @@ +{ + "name": "livereload-js", + "version": "2.2.1", + "main": "dist/livereload.js", + "homepage": "http://livereload.com", + "authors": [ + "Andrey Tarantsov <andrey@tarantsov.com>", + "David Kelso <david@kelso.id.au>" + ], + "description": "LiveReload JS client - auto reload browser on changes", + "keywords": [ + "javascript", + "livereload" + ], + "license": "MIT", + "ignore": [ + "Rakefile", + "lib", + "lib-cov", + "src", + "test", + "**/.*", + "node_modules", + "bower_components", + "tests" + ], + "moduleType": [ + "globals" + ] +} diff --git a/bower_components/livereload-js/dist/livereload.js b/bower_components/livereload-js/dist/livereload.js new file mode 100644 index 0000000..f6c3b7f --- /dev/null +++ b/bower_components/livereload-js/dist/livereload.js @@ -0,0 +1,1155 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ +(function() { + var Connector, PROTOCOL_6, PROTOCOL_7, Parser, Version, _ref; + + _ref = require('./protocol'), Parser = _ref.Parser, PROTOCOL_6 = _ref.PROTOCOL_6, PROTOCOL_7 = _ref.PROTOCOL_7; + + Version = '2.2.1'; + + exports.Connector = Connector = (function() { + function Connector(options, WebSocket, Timer, handlers) { + this.options = options; + this.WebSocket = WebSocket; + this.Timer = Timer; + this.handlers = handlers; + this._uri = "ws://" + this.options.host + ":" + this.options.port + "/livereload"; + this._nextDelay = this.options.mindelay; + this._connectionDesired = false; + this.protocol = 0; + this.protocolParser = new Parser({ + connected: (function(_this) { + return function(protocol) { + _this.protocol = protocol; + _this._handshakeTimeout.stop(); + _this._nextDelay = _this.options.mindelay; + _this._disconnectionReason = 'broken'; + return _this.handlers.connected(protocol); + }; + })(this), + error: (function(_this) { + return function(e) { + _this.handlers.error(e); + return _this._closeOnError(); + }; + })(this), + message: (function(_this) { + return function(message) { + return _this.handlers.message(message); + }; + })(this) + }); + this._handshakeTimeout = new Timer((function(_this) { + return function() { + if (!_this._isSocketConnected()) { + return; + } + _this._disconnectionReason = 'handshake-timeout'; + return _this.socket.close(); + }; + })(this)); + this._reconnectTimer = new Timer((function(_this) { + return function() { + if (!_this._connectionDesired) { + return; + } + return _this.connect(); + }; + })(this)); + this.connect(); + } + + Connector.prototype._isSocketConnected = function() { + return this.socket && this.socket.readyState === this.WebSocket.OPEN; + }; + + Connector.prototype.connect = function() { + this._connectionDesired = true; + if (this._isSocketConnected()) { + return; + } + this._reconnectTimer.stop(); + this._disconnectionReason = 'cannot-connect'; + this.protocolParser.reset(); + this.handlers.connecting(); + this.socket = new this.WebSocket(this._uri); + this.socket.onopen = (function(_this) { + return function(e) { + return _this._onopen(e); + }; + })(this); + this.socket.onclose = (function(_this) { + return function(e) { + return _this._onclose(e); + }; + })(this); + this.socket.onmessage = (function(_this) { + return function(e) { + return _this._onmessage(e); + }; + })(this); + return this.socket.onerror = (function(_this) { + return function(e) { + return _this._onerror(e); + }; + })(this); + }; + + Connector.prototype.disconnect = function() { + this._connectionDesired = false; + this._reconnectTimer.stop(); + if (!this._isSocketConnected()) { + return; + } + this._disconnectionReason = 'manual'; + return this.socket.close(); + }; + + Connector.prototype._scheduleReconnection = function() { + if (!this._connectionDesired) { + return; + } + if (!this._reconnectTimer.running) { + this._reconnectTimer.start(this._nextDelay); + return this._nextDelay = Math.min(this.options.maxdelay, this._nextDelay * 2); + } + }; + + Connector.prototype.sendCommand = function(command) { + if (this.protocol == null) { + return; + } + return this._sendCommand(command); + }; + + Connector.prototype._sendCommand = function(command) { + return this.socket.send(JSON.stringify(command)); + }; + + Connector.prototype._closeOnError = function() { + this._handshakeTimeout.stop(); + this._disconnectionReason = 'error'; + return this.socket.close(); + }; + + Connector.prototype._onopen = function(e) { + var hello; + this.handlers.socketConnected(); + this._disconnectionReason = 'handshake-failed'; + hello = { + command: 'hello', + protocols: [PROTOCOL_6, PROTOCOL_7] + }; + hello.ver = Version; + if (this.options.ext) { + hello.ext = this.options.ext; + } + if (this.options.extver) { + hello.extver = this.options.extver; + } + if (this.options.snipver) { + hello.snipver = this.options.snipver; + } + this._sendCommand(hello); + return this._handshakeTimeout.start(this.options.handshake_timeout); + }; + + Connector.prototype._onclose = function(e) { + this.protocol = 0; + this.handlers.disconnected(this._disconnectionReason, this._nextDelay); + return this._scheduleReconnection(); + }; + + Connector.prototype._onerror = function(e) {}; + + Connector.prototype._onmessage = function(e) { + return this.protocolParser.process(e.data); + }; + + return Connector; + + })(); + +}).call(this); + +},{"./protocol":6}],2:[function(require,module,exports){ +(function() { + var CustomEvents; + + CustomEvents = { + bind: function(element, eventName, handler) { + if (element.addEventListener) { + return element.addEventListener(eventName, handler, false); + } else if (element.attachEvent) { + element[eventName] = 1; + return element.attachEvent('onpropertychange', function(event) { + if (event.propertyName === eventName) { + return handler(); + } + }); + } else { + throw new Error("Attempt to attach custom event " + eventName + " to something which isn't a DOMElement"); + } + }, + fire: function(element, eventName) { + var event; + if (element.addEventListener) { + event = document.createEvent('HTMLEvents'); + event.initEvent(eventName, true, true); + return document.dispatchEvent(event); + } else if (element.attachEvent) { + if (element[eventName]) { + return element[eventName]++; + } + } else { + throw new Error("Attempt to fire custom event " + eventName + " on something which isn't a DOMElement"); + } + } + }; + + exports.bind = CustomEvents.bind; + + exports.fire = CustomEvents.fire; + +}).call(this); + +},{}],3:[function(require,module,exports){ +(function() { + var LessPlugin; + + module.exports = LessPlugin = (function() { + LessPlugin.identifier = 'less'; + + LessPlugin.version = '1.0'; + + function LessPlugin(window, host) { + this.window = window; + this.host = host; + } + + LessPlugin.prototype.reload = function(path, options) { + if (this.window.less && this.window.less.refresh) { + if (path.match(/\.less$/i)) { + return this.reloadLess(path); + } + if (options.originalPath.match(/\.less$/i)) { + return this.reloadLess(options.originalPath); + } + } + return false; + }; + + LessPlugin.prototype.reloadLess = function(path) { + var link, links, _i, _len; + links = (function() { + var _i, _len, _ref, _results; + _ref = document.getElementsByTagName('link'); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + if (link.href && link.rel.match(/^stylesheet\/less$/i) || (link.rel.match(/stylesheet/i) && link.type.match(/^text\/(x-)?less$/i))) { + _results.push(link); + } + } + return _results; + })(); + if (links.length === 0) { + return false; + } + for (_i = 0, _len = links.length; _i < _len; _i++) { + link = links[_i]; + link.href = this.host.generateCacheBustUrl(link.href); + } + this.host.console.log("LiveReload is asking LESS to recompile all stylesheets"); + this.window.less.refresh(true); + return true; + }; + + LessPlugin.prototype.analyze = function() { + return { + disable: !!(this.window.less && this.window.less.refresh) + }; + }; + + return LessPlugin; + + })(); + +}).call(this); + +},{}],4:[function(require,module,exports){ +(function() { + var Connector, LiveReload, Options, Reloader, Timer; + + Connector = require('./connector').Connector; + + Timer = require('./timer').Timer; + + Options = require('./options').Options; + + Reloader = require('./reloader').Reloader; + + exports.LiveReload = LiveReload = (function() { + function LiveReload(window) { + this.window = window; + this.listeners = {}; + this.plugins = []; + this.pluginIdentifiers = {}; + this.console = this.window.location.href.match(/LR-verbose/) && this.window.console && this.window.console.log && this.window.console.error ? this.window.console : { + log: function() {}, + error: function() {} + }; + if (!(this.WebSocket = this.window.WebSocket || this.window.MozWebSocket)) { + this.console.error("LiveReload disabled because the browser does not seem to support web sockets"); + return; + } + if (!(this.options = Options.extract(this.window.document))) { + this.console.error("LiveReload disabled because it could not find its own <SCRIPT> tag"); + return; + } + this.reloader = new Reloader(this.window, this.console, Timer); + this.connector = new Connector(this.options, this.WebSocket, Timer, { + connecting: (function(_this) { + return function() {}; + })(this), + socketConnected: (function(_this) { + return function() {}; + })(this), + connected: (function(_this) { + return function(protocol) { + var _base; + if (typeof (_base = _this.listeners).connect === "function") { + _base.connect(); + } + _this.log("LiveReload is connected to " + _this.options.host + ":" + _this.options.port + " (protocol v" + protocol + ")."); + return _this.analyze(); + }; + })(this), + error: (function(_this) { + return function(e) { + if (e instanceof ProtocolError) { + if (typeof console !== "undefined" && console !== null) { + return console.log("" + e.message + "."); + } + } else { + if (typeof console !== "undefined" && console !== null) { + return console.log("LiveReload internal error: " + e.message); + } + } + }; + })(this), + disconnected: (function(_this) { + return function(reason, nextDelay) { + var _base; + if (typeof (_base = _this.listeners).disconnect === "function") { + _base.disconnect(); + } + switch (reason) { + case 'cannot-connect': + return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + ", will retry in " + nextDelay + " sec."); + case 'broken': + return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + ", reconnecting in " + nextDelay + " sec."); + case 'handshake-timeout': + return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake timeout), will retry in " + nextDelay + " sec."); + case 'handshake-failed': + return _this.log("LiveReload cannot connect to " + _this.options.host + ":" + _this.options.port + " (handshake failed), will retry in " + nextDelay + " sec."); + case 'manual': + break; + case 'error': + break; + default: + return _this.log("LiveReload disconnected from " + _this.options.host + ":" + _this.options.port + " (" + reason + "), reconnecting in " + nextDelay + " sec."); + } + }; + })(this), + message: (function(_this) { + return function(message) { + switch (message.command) { + case 'reload': + return _this.performReload(message); + case 'alert': + return _this.performAlert(message); + } + }; + })(this) + }); + } + + LiveReload.prototype.on = function(eventName, handler) { + return this.listeners[eventName] = handler; + }; + + LiveReload.prototype.log = function(message) { + return this.console.log("" + message); + }; + + LiveReload.prototype.performReload = function(message) { + var _ref, _ref1; + this.log("LiveReload received reload request: " + (JSON.stringify(message, null, 2))); + return this.reloader.reload(message.path, { + liveCSS: (_ref = message.liveCSS) != null ? _ref : true, + liveImg: (_ref1 = message.liveImg) != null ? _ref1 : true, + originalPath: message.originalPath || '', + overrideURL: message.overrideURL || '', + serverURL: "http://" + this.options.host + ":" + this.options.port + }); + }; + + LiveReload.prototype.performAlert = function(message) { + return alert(message.message); + }; + + LiveReload.prototype.shutDown = function() { + var _base; + this.connector.disconnect(); + this.log("LiveReload disconnected."); + return typeof (_base = this.listeners).shutdown === "function" ? _base.shutdown() : void 0; + }; + + LiveReload.prototype.hasPlugin = function(identifier) { + return !!this.pluginIdentifiers[identifier]; + }; + + LiveReload.prototype.addPlugin = function(pluginClass) { + var plugin; + if (this.hasPlugin(pluginClass.identifier)) { + return; + } + this.pluginIdentifiers[pluginClass.identifier] = true; + plugin = new pluginClass(this.window, { + _livereload: this, + _reloader: this.reloader, + _connector: this.connector, + console: this.console, + Timer: Timer, + generateCacheBustUrl: (function(_this) { + return function(url) { + return _this.reloader.generateCacheBustUrl(url); + }; + })(this) + }); + this.plugins.push(plugin); + this.reloader.addPlugin(plugin); + }; + + LiveReload.prototype.analyze = function() { + var plugin, pluginData, pluginsData, _i, _len, _ref; + if (!(this.connector.protocol >= 7)) { + return; + } + pluginsData = {}; + _ref = this.plugins; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + plugin = _ref[_i]; + pluginsData[plugin.constructor.identifier] = pluginData = (typeof plugin.analyze === "function" ? plugin.analyze() : void 0) || {}; + pluginData.version = plugin.constructor.version; + } + this.connector.sendCommand({ + command: 'info', + plugins: pluginsData, + url: this.window.location.href + }); + }; + + return LiveReload; + + })(); + +}).call(this); + +},{"./connector":1,"./options":5,"./reloader":7,"./timer":9}],5:[function(require,module,exports){ +(function() { + var Options; + + exports.Options = Options = (function() { + function Options() { + this.host = null; + this.port = 35729; + this.snipver = null; + this.ext = null; + this.extver = null; + this.mindelay = 1000; + this.maxdelay = 60000; + this.handshake_timeout = 5000; + } + + Options.prototype.set = function(name, value) { + if (typeof value === 'undefined') { + return; + } + if (!isNaN(+value)) { + value = +value; + } + return this[name] = value; + }; + + return Options; + + })(); + + Options.extract = function(document) { + var element, keyAndValue, m, mm, options, pair, src, _i, _j, _len, _len1, _ref, _ref1; + _ref = document.getElementsByTagName('script'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + element = _ref[_i]; + if ((src = element.src) && (m = src.match(/^[^:]+:\/\/(.*)\/z?livereload\.js(?:\?(.*))?$/))) { + options = new Options(); + if (mm = m[1].match(/^([^\/:]+)(?::(\d+))?$/)) { + options.host = mm[1]; + if (mm[2]) { + options.port = parseInt(mm[2], 10); + } + } + if (m[2]) { + _ref1 = m[2].split('&'); + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + pair = _ref1[_j]; + if ((keyAndValue = pair.split('=')).length > 1) { + options.set(keyAndValue[0].replace(/-/g, '_'), keyAndValue.slice(1).join('=')); + } + } + } + return options; + } + } + return null; + }; + +}).call(this); + +},{}],6:[function(require,module,exports){ +(function() { + var PROTOCOL_6, PROTOCOL_7, Parser, ProtocolError, + __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + exports.PROTOCOL_6 = PROTOCOL_6 = 'http://livereload.com/protocols/official-6'; + + exports.PROTOCOL_7 = PROTOCOL_7 = 'http://livereload.com/protocols/official-7'; + + exports.ProtocolError = ProtocolError = (function() { + function ProtocolError(reason, data) { + this.message = "LiveReload protocol error (" + reason + ") after receiving data: \"" + data + "\"."; + } + + return ProtocolError; + + })(); + + exports.Parser = Parser = (function() { + function Parser(handlers) { + this.handlers = handlers; + this.reset(); + } + + Parser.prototype.reset = function() { + return this.protocol = null; + }; + + Parser.prototype.process = function(data) { + var command, e, message, options, _ref; + try { + if (this.protocol == null) { + if (data.match(/^!!ver:([\d.]+)$/)) { + this.protocol = 6; + } else if (message = this._parseMessage(data, ['hello'])) { + if (!message.protocols.length) { + throw new ProtocolError("no protocols specified in handshake message"); + } else if (__indexOf.call(message.protocols, PROTOCOL_7) >= 0) { + this.protocol = 7; + } else if (__indexOf.call(message.protocols, PROTOCOL_6) >= 0) { + this.protocol = 6; + } else { + throw new ProtocolError("no supported protocols found"); + } + } + return this.handlers.connected(this.protocol); + } else if (this.protocol === 6) { + message = JSON.parse(data); + if (!message.length) { + throw new ProtocolError("protocol 6 messages must be arrays"); + } + command = message[0], options = message[1]; + if (command !== 'refresh') { + throw new ProtocolError("unknown protocol 6 command"); + } + return this.handlers.message({ + command: 'reload', + path: options.path, + liveCSS: (_ref = options.apply_css_live) != null ? _ref : true + }); + } else { + message = this._parseMessage(data, ['reload', 'alert']); + return this.handlers.message(message); + } + } catch (_error) { + e = _error; + if (e instanceof ProtocolError) { + return this.handlers.error(e); + } else { + throw e; + } + } + }; + + Parser.prototype._parseMessage = function(data, validCommands) { + var e, message, _ref; + try { + message = JSON.parse(data); + } catch (_error) { + e = _error; + throw new ProtocolError('unparsable JSON', data); + } + if (!message.command) { + throw new ProtocolError('missing "command" key', data); + } + if (_ref = message.command, __indexOf.call(validCommands, _ref) < 0) { + throw new ProtocolError("invalid command '" + message.command + "', only valid commands are: " + (validCommands.join(', ')) + ")", data); + } + return message; + }; + + return Parser; + + })(); + +}).call(this); + +},{}],7:[function(require,module,exports){ +(function() { + var IMAGE_STYLES, Reloader, numberOfMatchingSegments, pathFromUrl, pathsMatch, pickBestMatch, splitUrl; + + splitUrl = function(url) { + var hash, index, params; + if ((index = url.indexOf('#')) >= 0) { + hash = url.slice(index); + url = url.slice(0, index); + } else { + hash = ''; + } + if ((index = url.indexOf('?')) >= 0) { + params = url.slice(index); + url = url.slice(0, index); + } else { + params = ''; + } + return { + url: url, + params: params, + hash: hash + }; + }; + + pathFromUrl = function(url) { + var path; + url = splitUrl(url).url; + if (url.indexOf('file://') === 0) { + path = url.replace(/^file:\/\/(localhost)?/, ''); + } else { + path = url.replace(/^([^:]+:)?\/\/([^:\/]+)(:\d*)?\//, '/'); + } + return decodeURIComponent(path); + }; + + pickBestMatch = function(path, objects, pathFunc) { + var bestMatch, object, score, _i, _len; + bestMatch = { + score: 0 + }; + for (_i = 0, _len = objects.length; _i < _len; _i++) { + object = objects[_i]; + score = numberOfMatchingSegments(path, pathFunc(object)); + if (score > bestMatch.score) { + bestMatch = { + object: object, + score: score + }; + } + } + if (bestMatch.score > 0) { + return bestMatch; + } else { + return null; + } + }; + + numberOfMatchingSegments = function(path1, path2) { + var comps1, comps2, eqCount, len; + path1 = path1.replace(/^\/+/, '').toLowerCase(); + path2 = path2.replace(/^\/+/, '').toLowerCase(); + if (path1 === path2) { + return 10000; + } + comps1 = path1.split('/').reverse(); + comps2 = path2.split('/').reverse(); + len = Math.min(comps1.length, comps2.length); + eqCount = 0; + while (eqCount < len && comps1[eqCount] === comps2[eqCount]) { + ++eqCount; + } + return eqCount; + }; + + pathsMatch = function(path1, path2) { + return numberOfMatchingSegments(path1, path2) > 0; + }; + + IMAGE_STYLES = [ + { + selector: 'background', + styleNames: ['backgroundImage'] + }, { + selector: 'border', + styleNames: ['borderImage', 'webkitBorderImage', 'MozBorderImage'] + } + ]; + + exports.Reloader = Reloader = (function() { + function Reloader(window, console, Timer) { + this.window = window; + this.console = console; + this.Timer = Timer; + this.document = this.window.document; + this.importCacheWaitPeriod = 200; + this.plugins = []; + } + + Reloader.prototype.addPlugin = function(plugin) { + return this.plugins.push(plugin); + }; + + Reloader.prototype.analyze = function(callback) { + return results; + }; + + Reloader.prototype.reload = function(path, options) { + var plugin, _base, _i, _len, _ref; + this.options = options; + if ((_base = this.options).stylesheetReloadTimeout == null) { + _base.stylesheetReloadTimeout = 15000; + } + _ref = this.plugins; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + plugin = _ref[_i]; + if (plugin.reload && plugin.reload(path, options)) { + return; + } + } + if (options.liveCSS) { + if (path.match(/\.css$/i)) { + if (this.reloadStylesheet(path)) { + return; + } + } + } + if (options.liveImg) { + if (path.match(/\.(jpe?g|png|gif)$/i)) { + this.reloadImages(path); + return; + } + } + return this.reloadPage(); + }; + + Reloader.prototype.reloadPage = function() { + return this.window.document.location.reload(); + }; + + Reloader.prototype.reloadImages = function(path) { + var expando, img, selector, styleNames, styleSheet, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _ref3, _results; + expando = this.generateUniqueString(); + _ref = this.document.images; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + img = _ref[_i]; + if (pathsMatch(path, pathFromUrl(img.src))) { + img.src = this.generateCacheBustUrl(img.src, expando); + } + } + if (this.document.querySelectorAll) { + for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { + _ref1 = IMAGE_STYLES[_j], selector = _ref1.selector, styleNames = _ref1.styleNames; + _ref2 = this.document.querySelectorAll("[style*=" + selector + "]"); + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + img = _ref2[_k]; + this.reloadStyleImages(img.style, styleNames, path, expando); + } + } + } + if (this.document.styleSheets) { + _ref3 = this.document.styleSheets; + _results = []; + for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { + styleSheet = _ref3[_l]; + _results.push(this.reloadStylesheetImages(styleSheet, path, expando)); + } + return _results; + } + }; + + Reloader.prototype.reloadStylesheetImages = function(styleSheet, path, expando) { + var e, rule, rules, styleNames, _i, _j, _len, _len1; + try { + rules = styleSheet != null ? styleSheet.cssRules : void 0; + } catch (_error) { + e = _error; + } + if (!rules) { + return; + } + for (_i = 0, _len = rules.length; _i < _len; _i++) { + rule = rules[_i]; + switch (rule.type) { + case CSSRule.IMPORT_RULE: + this.reloadStylesheetImages(rule.styleSheet, path, expando); + break; + case CSSRule.STYLE_RULE: + for (_j = 0, _len1 = IMAGE_STYLES.length; _j < _len1; _j++) { + styleNames = IMAGE_STYLES[_j].styleNames; + this.reloadStyleImages(rule.style, styleNames, path, expando); + } + break; + case CSSRule.MEDIA_RULE: + this.reloadStylesheetImages(rule, path, expando); + } + } + }; + + Reloader.prototype.reloadStyleImages = function(style, styleNames, path, expando) { + var newValue, styleName, value, _i, _len; + for (_i = 0, _len = styleNames.length; _i < _len; _i++) { + styleName = styleNames[_i]; + value = style[styleName]; + if (typeof value === 'string') { + newValue = value.replace(/\burl\s*\(([^)]*)\)/, (function(_this) { + return function(match, src) { + if (pathsMatch(path, pathFromUrl(src))) { + return "url(" + (_this.generateCacheBustUrl(src, expando)) + ")"; + } else { + return match; + } + }; + })(this)); + if (newValue !== value) { + style[styleName] = newValue; + } + } + } + }; + + Reloader.prototype.reloadStylesheet = function(path) { + var imported, link, links, match, style, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1; + links = (function() { + var _i, _len, _ref, _results; + _ref = this.document.getElementsByTagName('link'); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + link = _ref[_i]; + if (link.rel.match(/^stylesheet$/i) && !link.__LiveReload_pendingRemoval) { + _results.push(link); + } + } + return _results; + }).call(this); + imported = []; + _ref = this.document.getElementsByTagName('style'); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + style = _ref[_i]; + if (style.sheet) { + this.collectImportedStylesheets(style, style.sheet, imported); + } + } + for (_j = 0, _len1 = links.length; _j < _len1; _j++) { + link = links[_j]; + this.collectImportedStylesheets(link, link.sheet, imported); + } + if (this.window.StyleFix && this.document.querySelectorAll) { + _ref1 = this.document.querySelectorAll('style[data-href]'); + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + style = _ref1[_k]; + links.push(style); + } + } + this.console.log("LiveReload found " + links.length + " LINKed stylesheets, " + imported.length + " @imported stylesheets"); + match = pickBestMatch(path, links.concat(imported), (function(_this) { + return function(l) { + return pathFromUrl(_this.linkHref(l)); + }; + })(this)); + if (match) { + if (match.object.rule) { + this.console.log("LiveReload is reloading imported stylesheet: " + match.object.href); + this.reattachImportedRule(match.object); + } else { + this.console.log("LiveReload is reloading stylesheet: " + (this.linkHref(match.object))); + this.reattachStylesheetLink(match.object); + } + } else { + this.console.log("LiveReload will reload all stylesheets because path '" + path + "' did not match any specific one"); + for (_l = 0, _len3 = links.length; _l < _len3; _l++) { + link = links[_l]; + this.reattachStylesheetLink(link); + } + } + return true; + }; + + Reloader.prototype.collectImportedStylesheets = function(link, styleSheet, result) { + var e, index, rule, rules, _i, _len; + try { + rules = styleSheet != null ? styleSheet.cssRules : void 0; + } catch (_error) { + e = _error; + } + if (rules && rules.length) { + for (index = _i = 0, _len = rules.length; _i < _len; index = ++_i) { + rule = rules[index]; + switch (rule.type) { + case CSSRule.CHARSET_RULE: + continue; + case CSSRule.IMPORT_RULE: + result.push({ + link: link, + rule: rule, + index: index, + href: rule.href + }); + this.collectImportedStylesheets(link, rule.styleSheet, result); + break; + default: + break; + } + } + } + }; + + Reloader.prototype.waitUntilCssLoads = function(clone, func) { + var callbackExecuted, executeCallback, poll; + callbackExecuted = false; + executeCallback = (function(_this) { + return function() { + if (callbackExecuted) { + return; + } + callbackExecuted = true; + return func(); + }; + })(this); + clone.onload = (function(_this) { + return function() { + _this.console.log("LiveReload: the new stylesheet has finished loading"); + _this.knownToSupportCssOnLoad = true; + return executeCallback(); + }; + })(this); + if (!this.knownToSupportCssOnLoad) { + (poll = (function(_this) { + return function() { + if (clone.sheet) { + _this.console.log("LiveReload is polling until the new CSS finishes loading..."); + return executeCallback(); + } else { + return _this.Timer.start(50, poll); + } + }; + })(this))(); + } + return this.Timer.start(this.options.stylesheetReloadTimeout, executeCallback); + }; + + Reloader.prototype.linkHref = function(link) { + return link.href || link.getAttribute('data-href'); + }; + + Reloader.prototype.reattachStylesheetLink = function(link) { + var clone, parent; + if (link.__LiveReload_pendingRemoval) { + return; + } + link.__LiveReload_pendingRemoval = true; + if (link.tagName === 'STYLE') { + clone = this.document.createElement('link'); + clone.rel = 'stylesheet'; + clone.media = link.media; + clone.disabled = link.disabled; + } else { + clone = link.cloneNode(false); + } + clone.href = this.generateCacheBustUrl(this.linkHref(link)); + parent = link.parentNode; + if (parent.lastChild === link) { + parent.appendChild(clone); + } else { + parent.insertBefore(clone, link.nextSibling); + } + return this.waitUntilCssLoads(clone, (function(_this) { + return function() { + var additionalWaitingTime; + if (/AppleWebKit/.test(navigator.userAgent)) { + additionalWaitingTime = 5; + } else { + additionalWaitingTime = 200; + } + return _this.Timer.start(additionalWaitingTime, function() { + var _ref; + if (!link.parentNode) { + return; + } + link.parentNode.removeChild(link); + clone.onreadystatechange = null; + return (_ref = _this.window.StyleFix) != null ? _ref.link(clone) : void 0; + }); + }; + })(this)); + }; + + Reloader.prototype.reattachImportedRule = function(_arg) { + var href, index, link, media, newRule, parent, rule, tempLink; + rule = _arg.rule, index = _arg.index, link = _arg.link; + parent = rule.parentStyleSheet; + href = this.generateCacheBustUrl(rule.href); + media = rule.media.length ? [].join.call(rule.media, ', ') : ''; + newRule = "@import url(\"" + href + "\") " + media + ";"; + rule.__LiveReload_newHref = href; + tempLink = this.document.createElement("link"); + tempLink.rel = 'stylesheet'; + tempLink.href = href; + tempLink.__LiveReload_pendingRemoval = true; + if (link.parentNode) { + link.parentNode.insertBefore(tempLink, link); + } + return this.Timer.start(this.importCacheWaitPeriod, (function(_this) { + return function() { + if (tempLink.parentNode) { + tempLink.parentNode.removeChild(tempLink); + } + if (rule.__LiveReload_newHref !== href) { + return; + } + parent.insertRule(newRule, index); + parent.deleteRule(index + 1); + rule = parent.cssRules[index]; + rule.__LiveReload_newHref = href; + return _this.Timer.start(_this.importCacheWaitPeriod, function() { + if (rule.__LiveReload_newHref !== href) { + return; + } + parent.insertRule(newRule, index); + return parent.deleteRule(index + 1); + }); + }; + })(this)); + }; + + Reloader.prototype.generateUniqueString = function() { + return 'livereload=' + Date.now(); + }; + + Reloader.prototype.generateCacheBustUrl = function(url, expando) { + var hash, oldParams, originalUrl, params, _ref; + if (expando == null) { + expando = this.generateUniqueString(); + } + _ref = splitUrl(url), url = _ref.url, hash = _ref.hash, oldParams = _ref.params; + if (this.options.overrideURL) { + if (url.indexOf(this.options.serverURL) < 0) { + originalUrl = url; + url = this.options.serverURL + this.options.overrideURL + "?url=" + encodeURIComponent(url); + this.console.log("LiveReload is overriding source URL " + originalUrl + " with " + url); + } + } + params = oldParams.replace(/(\?|&)livereload=(\d+)/, function(match, sep) { + return "" + sep + expando; + }); + if (params === oldParams) { + if (oldParams.length === 0) { + params = "?" + expando; + } else { + params = "" + oldParams + "&" + expando; + } + } + return url + params + hash; + }; + + return Reloader; + + })(); + +}).call(this); + +},{}],8:[function(require,module,exports){ +(function() { + var CustomEvents, LiveReload, k; + + CustomEvents = require('./customevents'); + + LiveReload = window.LiveReload = new (require('./livereload').LiveReload)(window); + + for (k in window) { + if (k.match(/^LiveReloadPlugin/)) { + LiveReload.addPlugin(window[k]); + } + } + + LiveReload.addPlugin(require('./less')); + + LiveReload.on('shutdown', function() { + return delete window.LiveReload; + }); + + LiveReload.on('connect', function() { + return CustomEvents.fire(document, 'LiveReloadConnect'); + }); + + LiveReload.on('disconnect', function() { + return CustomEvents.fire(document, 'LiveReloadDisconnect'); + }); + + CustomEvents.bind(document, 'LiveReloadShutDown', function() { + return LiveReload.shutDown(); + }); + +}).call(this); + +},{"./customevents":2,"./less":3,"./livereload":4}],9:[function(require,module,exports){ +(function() { + var Timer; + + exports.Timer = Timer = (function() { + function Timer(func) { + this.func = func; + this.running = false; + this.id = null; + this._handler = (function(_this) { + return function() { + _this.running = false; + _this.id = null; + return _this.func(); + }; + })(this); + } + + Timer.prototype.start = function(timeout) { + if (this.running) { + clearTimeout(this.id); + } + this.id = setTimeout(this._handler, timeout); + return this.running = true; + }; + + Timer.prototype.stop = function() { + if (this.running) { + clearTimeout(this.id); + this.running = false; + return this.id = null; + } + }; + + return Timer; + + })(); + + Timer.start = function(timeout, func) { + return setTimeout(func, timeout); + }; + +}).call(this); + +},{}]},{},[8]); diff --git a/bower_components/livereload-js/package.json b/bower_components/livereload-js/package.json new file mode 100644 index 0000000..a74aa53 --- /dev/null +++ b/bower_components/livereload-js/package.json @@ -0,0 +1,32 @@ +{ + "name": "livereload-js", + "version": "2.2.1", + "description": "LiveReload JS client - auto reload browser on changes", + "main": "lib/startup.js", + "directories": { + "test": "test" + }, + "devDependencies": { + "coffee-script": "~1.7.1", + "expresso": "~0.9.2", + "grunt": "^0.4.5", + "grunt-browserify": "^3.3.0", + "grunt-contrib-coffee": "^0.12.0", + "grunt-mocha-test": "^0.12.6", + "jsdom": "~0.10.5", + "mocha": "^2.1.0" + }, + "scripts": { + "prepublish": "grunt build", + "test": "grunt test" + }, + "repository": { + "type": "git", + "url": "git://github.com/zaius/livereload-js.git" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/zaius/livereload-js/issues" + }, + "homepage": "https://github.com/zaius/livereload-js" +} diff --git a/bower_components/moment/.bower.json b/bower_components/moment/.bower.json new file mode 100644 index 0000000..99c7933 --- /dev/null +++ b/bower_components/moment/.bower.json @@ -0,0 +1,33 @@ +{ + "name": "moment", + "version": "2.10.3", + "main": "moment.js", + "ignore": [ + "**/.*", + "benchmarks", + "bower_components", + "meteor", + "node_modules", + "scripts", + "tasks", + "test", + "component.json", + "composer.json", + "CONTRIBUTING.md", + "ender.js", + "Gruntfile.js", + "Moment.js.nuspec", + "package.js", + "package.json" + ], + "homepage": "https://github.com/moment/moment", + "_release": "2.10.3", + "_resolution": { + "type": "version", + "tag": "2.10.3", + "commit": "6fa444238494318e3c488c81d8520ad2eba8bae7" + }, + "_source": "git://github.com/moment/moment.git", + "_target": "~2.10.3", + "_originalSource": "moment" +}
\ No newline at end of file diff --git a/bower_components/moment/CHANGELOG.md b/bower_components/moment/CHANGELOG.md new file mode 100644 index 0000000..395261f --- /dev/null +++ b/bower_components/moment/CHANGELOG.md @@ -0,0 +1,441 @@ +Changelog +========= + +### 2.10.3 [See full changelog](https://gist.github.com/ichernev/f264b9bed5b00f8b1b7f) + +* add `moment.fn.to` and `moment.fn.toNow` (similar to `from` and `fromNow`) +* new locales (Sinhalese (si), Montenegrin (me), Javanese (ja)) +* performance improvements + +### 2.10.2 + +* fixed moment-with-locales in browser env caused by esperanto change + +### 2.10.1 + +* regression: Add moment.duration.fn back + +### 2.10.0 + +Ported code to es6 modules. + +### 2.9.0 [See full changelog](https://gist.github.com/ichernev/0c9a9b49951111a27ce7) + +languages: +* [2104](https://github.com/moment/moment/issues/2104) Frisian (fy) language file with unit test +* [2097](https://github.com/moment/moment/issues/2097) add ar-tn locale + +deprecations: +* [2074](https://github.com/moment/moment/issues/2074) Implement `moment.fn.utcOffset`, deprecate `momen.fn.zone` + +features: +* [2088](https://github.com/moment/moment/issues/2088) add moment.fn.isBetween +* [2054](https://github.com/moment/moment/issues/2054) Call updateOffset when creating moment (needed for default timezone in + moment-timezone) +* [1893](https://github.com/moment/moment/issues/1893) Add moment.isDate method +* [1825](https://github.com/moment/moment/issues/1825) Implement toJSON function on Duration +* [1809](https://github.com/moment/moment/issues/1809) Allowing moment.set() to accept a hash of units +* [2128](https://github.com/moment/moment/issues/2128) Add firstDayOfWeek, firstDayOfYear locale getters +* [2131](https://github.com/moment/moment/issues/2131) Add quarter diff support + +Some bugfixes and language improvements -- [full changelog](https://gist.github.com/ichernev/0c9a9b49951111a27ce7) + +### 2.8.4 [See full changelog](https://gist.github.com/ichernev/a4fcb0a46d74e4b9b996) + +Features: + +* [#2000](https://github.com/moment/moment/issues/2000) Add LTS localised format that includes seconds +* [#1960](https://github.com/moment/moment/issues/1960) added formatToken 'x' for unix offset in milliseconds #1938 +* [#1965](https://github.com/moment/moment/issues/1965) Support 24:00:00.000 to mean next day, at midnight. +* [#2002](https://github.com/moment/moment/issues/2002) Accept 'date' key when creating moment with object +* [#2009](https://github.com/moment/moment/issues/2009) Use native toISOString when we can + +Some bugfixes and language improvements -- [full changelog](https://gist.github.com/ichernev/a4fcb0a46d74e4b9b996) + +### 2.8.3 + +Bugfixes: + +* [#1801](https://github.com/moment/moment/issues/1801) proper pluralization for Arabic +* [#1833](https://github.com/moment/moment/issues/1833) improve spm integration +* [#1871](https://github.com/moment/moment/issues/1871) fix zone bug caused by Firefox 24 +* [#1882](https://github.com/moment/moment/issues/1882) Use hh:mm in Czech +* [#1883](https://github.com/moment/moment/issues/1883) Fix 2.8.0 regression in duration as conversions +* [#1890](https://github.com/moment/moment/issues/1890) Faster travis builds +* [#1892](https://github.com/moment/moment/issues/1892) Faster isBefore/After/Same +* [#1848](https://github.com/moment/moment/issues/1848) Fix flaky month diffs +* [#1895](https://github.com/moment/moment/issues/1895) Fix 2.8.0 regression in moment.utc with format array +* [#1896](https://github.com/moment/moment/issues/1896) Support setting invalid instance locale (noop) +* [#1897](https://github.com/moment/moment/issues/1897) Support moment([str]) in addition to moment([int]) + +### 2.8.2 + +Minor bugfixes: + +* [#1874](https://github.com/moment/moment/issues/1874) use `Object.prototype.hasOwnProperty` + instead of `obj.hasOwnProperty` (ie8 bug) +* [#1873](https://github.com/moment/moment/issues/1873) add `duration#toString()` +* [#1859](https://github.com/moment/moment/issues/1859) better month/weekday names in norwegian +* [#1812](https://github.com/moment/moment/issues/1812) meridiem parsing for greek +* [#1804](https://github.com/moment/moment/issues/1804) spanish del -> de +* [#1800](https://github.com/moment/moment/issues/1800) korean LT improvement + +### 2.8.1 + +* bugfix [#1813](https://github.com/moment/moment/issues/1813): fix moment().lang([key]) incompatibility + +### 2.8.0 [See changelog](https://gist.github.com/ichernev/ac3899324a5fa6c8c9b4) + +* incompatible changes + * [#1761](https://github.com/moment/moment/issues/1761): moments created without a language are no longer following the global language, in case it changes. Only newly created moments take the global language by default. In case you're affected by this, wait, comment on [#1797](https://github.com/moment/moment/issues/1797) and wait for a proper reimplementation + * [#1642](https://github.com/moment/moment/issues/1642): 45 days is no longer "a month" according to humanize, cutoffs for month, and year have changed. Hopefully your code does not depend on a particular answer from humanize (which it shouldn't anyway) + * [#1784](https://github.com/moment/moment/issues/1784): if you use the human readable English datetime format in a weird way (like storing them in a database) that would break when the format changes you're at risk. + +* deprecations (old behavior will be dropped in 3.0) + * [#1761](https://github.com/moment/moment/issues/1761) `lang` is renamed to `locale`, `langData` -> `localeData`. Also there is now `defineLocale` that should be used when creating new locales + * [#1763](https://github.com/moment/moment/issues/1763) `add(unit, value)` and `subtract(unit, value)` are now deprecated. Use `add(value, unit)` and `subtract(value, unit)` instead. + * [#1759](https://github.com/moment/moment/issues/1759) rename `duration.toIsoString` to `duration.toISOString`. The js standard library and moment's `toISOString` follow that convention. + +* new locales + * [#1789](https://github.com/moment/moment/issues/1789) Tibetan (bo) + * [#1786](https://github.com/moment/moment/issues/1786) Africaans (af) + * [#1778](https://github.com/moment/moment/issues/1778) Burmese (my) + * [#1727](https://github.com/moment/moment/issues/1727) Belarusian (be) + +* bugfixes, locale bugfixes, performance improvements, features + +### 2.7.0 [See changelog](https://gist.github.com/ichernev/b0a3d456d5a84c9901d7) + +* new languages + + * [#1678](https://github.com/moment/moment/issues/1678) Bengali (bn) + * [#1628](https://github.com/moment/moment/issues/1628) Azerbaijani (az) + * [#1633](https://github.com/moment/moment/issues/1633) Arabic, Saudi Arabia (ar-sa) + * [#1648](https://github.com/moment/moment/issues/1648) Austrian German (de-at) + +* features + + * [#1663](https://github.com/moment/moment/issues/1663) configurable relative time thresholds + * [#1554](https://github.com/moment/moment/issues/1554) support anchor time in moment.calendar + * [#1693](https://github.com/moment/moment/issues/1693) support moment.ISO_8601 as parsing format + * [#1637](https://github.com/moment/moment/issues/1637) add moment.min and moment.max and deprecate min/max instance methods + * [#1704](https://github.com/moment/moment/issues/1704) support string value in add/subtract + * [#1647](https://github.com/moment/moment/issues/1647) add spm support (package manager) + +* bugfixes + +### 2.6.0 [See changelog](https://gist.github.com/ichernev/10544682) + +* languages + * [#1529](https://github.com/moment/moment/issues/1529) Serbian-Cyrillic (sr-cyr) + * [#1544](https://github.com/moment/moment/issues/1544), [#1546](https://github.com/moment/moment/issues/1546) Khmer Cambodia (km) + +* features + * [#1419](https://github.com/moment/moment/issues/1419), [#1468](https://github.com/moment/moment/issues/1468), [#1467](https://github.com/moment/moment/issues/1467), [#1546](https://github.com/moment/moment/issues/1546) better handling of timezone-d moments around DST + * [#1462](https://github.com/moment/moment/issues/1462) add weeksInYear and isoWeeksInYear + * [#1475](https://github.com/moment/moment/issues/1475) support ordinal parsing + * [#1499](https://github.com/moment/moment/issues/1499) composer support + * [#1577](https://github.com/moment/moment/issues/1577), [#1604](https://github.com/moment/moment/issues/1604) put Date parsing in moment.createFromInputFallback so it can be properly deprecated and controlled in the future + * [#1545](https://github.com/moment/moment/issues/1545) extract two-digit year parsing in moment.parseTwoDigitYear, so it can be overwritten + * [#1590](https://github.com/moment/moment/issues/1590) (see [#1574](https://github.com/moment/moment/issues/1574)) set AMD global before module definition to better support non AMD module dependencies used in AMD environment + * [#1589](https://github.com/moment/moment/issues/1589) remove global in Node.JS environment (was not working before, nobody complained, was scheduled for removal anyway) + * [#1586](https://github.com/moment/moment/issues/1586) support quarter setting and parsing + +* 18 bugs fixed + +### 2.5.1 + +* languages + * [#1392](https://github.com/moment/moment/issues/1392) Armenian (hy-am) + +* bugfixes + * [#1429](https://github.com/moment/moment/issues/1429) fixes [#1423](https://github.com/moment/moment/issues/1423) weird chrome-32 bug with js object creation + * [#1421](https://github.com/moment/moment/issues/1421) remove html entities from Welsh + * [#1418](https://github.com/moment/moment/issues/1418) fixes [#1401](https://github.com/moment/moment/issues/1401) improved non-padded tokens in strict matching + * [#1417](https://github.com/moment/moment/issues/1417) fixes [#1404](https://github.com/moment/moment/issues/1404) handle buggy moment object created by property cloning + * [#1398](https://github.com/moment/moment/issues/1398) fixes [#1397](https://github.com/moment/moment/issues/1397) fix Arabic-like week number parsing + * [#1396](https://github.com/moment/moment/issues/1396) add leftZeroFill(4) to GGGG and gggg formats + * [#1373](https://github.com/moment/moment/issues/1373) use lowercase for months and days in Catalan + +* testing + * [#1374](https://github.com/moment/moment/issues/1374) run tests on multiple browser/os combos via SauceLabs and Travis + +### 2.5.0 [See changelog](https://gist.github.com/ichernev/8104451) + +* New languages + * Luxemburish (lb) [1247](https://github.com/moment/moment/issues/1247) + * Serbian (rs) [1319](https://github.com/moment/moment/issues/1319) + * Tamil (ta) [1324](https://github.com/moment/moment/issues/1324) + * Macedonian (mk) [1337](https://github.com/moment/moment/issues/1337) + +* Features + * [1311](https://github.com/moment/moment/issues/1311) Add quarter getter and format token `Q` + * [1303](https://github.com/moment/moment/issues/1303) strict parsing now respects number of digits per token (fix [1196](https://github.com/moment/moment/issues/1196)) + * 0d30bb7 add jspm support + * [1347](https://github.com/moment/moment/issues/1347) improve zone parsing + * [1362](https://github.com/moment/moment/issues/1362) support merideam parsing in Korean + +* 22 bugfixes + +### 2.4.0 + +* **Deprecate** globally exported moment, will be removed in next major +* New languages + * Farose (fo) [#1206](https://github.com/moment/moment/issues/1206) + * Tagalog/Filipino (tl-ph) [#1197](https://github.com/moment/moment/issues/1197) + * Welsh (cy) [#1215](https://github.com/moment/moment/issues/1215) +* Bugfixes + * properly handle Z at the end of iso RegExp [#1187](https://github.com/moment/moment/issues/1187) + * chinese meridian time improvements [#1076](https://github.com/moment/moment/issues/1076) + * fix language tests [#1177](https://github.com/moment/moment/issues/1177) + * remove some failing tests (that should have never existed :)) + [#1185](https://github.com/moment/moment/issues/1185) + [#1183](https://github.com/moment/moment/issues/1183) + * handle russian noun cases in weird cases [#1195](https://github.com/moment/moment/issues/1195) + +### 2.3.1 + +Removed a trailing comma [1169] and fixed a bug with `months`, `weekdays` getters [#1171](https://github.com/moment/moment/issues/1171). + +### 2.3.0 [See changelog](https://gist.github.com/ichernev/6864354) + +Changed isValid, added strict parsing. +Week tokens parsing. + +### 2.2.1 + +Fixed bug in string prototype test. +Updated authors and contributors. + +### 2.2.0 [See changelog](https://gist.github.com/ichernev/00f837a9baf46a3565e4) + +Added bower support. + +Language files now use UMD. + +Creating moment defaults to current date/month/year. + +Added a bundle of moment and all language files. + +### 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 + diff --git a/bower_components/moment/LICENSE b/bower_components/moment/LICENSE new file mode 100644 index 0000000..34f5b37 --- /dev/null +++ b/bower_components/moment/LICENSE @@ -0,0 +1,22 @@ +Copyright (c) 2011-2015 Tim Wood, Iskren Chernev, Moment.js contributors + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/bower_components/moment/README.md b/bower_components/moment/README.md new file mode 100644 index 0000000..d5fc00a --- /dev/null +++ b/bower_components/moment/README.md @@ -0,0 +1,57 @@ +[](https://gitter.im/moment/moment?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) + +[![NPM version][npm-version-image]][npm-url] [![NPM downloads][npm-downloads-image]][npm-url] [![MIT License][license-image]][license-url] [![Build Status][travis-image]][travis-url] + +A lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates. + +## [Documentation](http://momentjs.com/docs/) + +## Port to ES6 (version 2.10.0) + +Moment 2.10.0 does not bring any new features, but the code is now written in +es6 modules and placed inside `src/`. Previously `moment.js`, `locale/*.js` and +`test/moment/*.js`, `test/locale/*.js` contained the source of the project. Now +the source is in `src/`, temporary build (es5) files are placed under +`build/umd/` (for running tests during development), and the `moment.js` and +`locale/*.js` files are updated only on release. + +If you want to use a particular revision of the code, make sure to run +`grunt transpile update-index`, so `moment.js` and `locales/*.js` are synced +with `src/*`. We might place that in a commit hook in the future. + +## Upgrading to 2.0.0 + +There are a number of small backwards incompatible changes with version 2.0.0. [See the full 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. + +## [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md) + +## [Contributing](https://github.com/moment/moment/blob/develop/CONTRIBUTING.md) + +We're looking for co-maintainers! If you want to become a master of time please +write to [ichernev](https://github.com/ichernev). + +## License + +Moment.js is freely distributable under the terms of the [MIT license](https://github.com/moment/moment/blob/develop/LICENSE). + +[license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat +[license-url]: LICENSE + +[npm-url]: https://npmjs.org/package/moment +[npm-version-image]: http://img.shields.io/npm/v/moment.svg?style=flat +[npm-downloads-image]: http://img.shields.io/npm/dm/moment.svg?style=flat + +[travis-url]: http://travis-ci.org/moment/moment +[travis-image]: http://img.shields.io/travis/moment/moment/develop.svg?style=flat diff --git a/bower_components/moment/bower.json b/bower_components/moment/bower.json new file mode 100644 index 0000000..48d24c7 --- /dev/null +++ b/bower_components/moment/bower.json @@ -0,0 +1,23 @@ +{ + "name": "moment", + "version": "2.10.3", + "main": "moment.js", + "ignore": [ + "**/.*", + "benchmarks", + "bower_components", + "meteor", + "node_modules", + "scripts", + "tasks", + "test", + "component.json", + "composer.json", + "CONTRIBUTING.md", + "ender.js", + "Gruntfile.js", + "Moment.js.nuspec", + "package.js", + "package.json" + ] +} diff --git a/bower_components/moment/locale/af.js b/bower_components/moment/locale/af.js new file mode 100644 index 0000000..341170b --- /dev/null +++ b/bower_components/moment/locale/af.js @@ -0,0 +1,72 @@ +//! moment.js locale configuration +//! locale : afrikaans (af) +//! author : Werner Mollentze : https://github.com/wernerm + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var af = moment.defineLocale('af', { + months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'), + weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'), + weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'), + meridiemParse: /vm|nm/i, + isPM : function (input) { + return /^nm$/i.test(input); + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower ? 'vm' : 'VM'; + } else { + return isLower ? 'nm' : 'NM'; + } + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd, D MMMM YYYY LT' + }, + calendar : { + sameDay : '[Vandag om] LT', + nextDay : '[Môre om] LT', + nextWeek : 'dddd [om] LT', + lastDay : '[Gister om] LT', + lastWeek : '[Laas] dddd [om] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'oor %s', + past : '%s gelede', + s : '\'n paar sekondes', + m : '\'n minuut', + mm : '%d minute', + h : '\'n uur', + hh : '%d ure', + d : '\'n dag', + dd : '%d dae', + M : '\'n maand', + MM : '%d maande', + y : '\'n jaar', + yy : '%d jaar' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter + }, + week : { + dow : 1, // Maandag is die eerste dag van die week. + doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar. + } + }); + + return af; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ar-ma.js b/bower_components/moment/locale/ar-ma.js new file mode 100644 index 0000000..aa50dd8 --- /dev/null +++ b/bower_components/moment/locale/ar-ma.js @@ -0,0 +1,58 @@ +//! moment.js locale configuration +//! locale : Moroccan Arabic (ar-ma) +//! author : ElFadili Yassine : https://github.com/ElFadiliY +//! author : Abdel Said : https://github.com/abdelsaid + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ar_ma = moment.defineLocale('ar-ma', { + months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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. + } + }); + + return ar_ma; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ar-sa.js b/bower_components/moment/locale/ar-sa.js new file mode 100644 index 0000000..ef5da5b --- /dev/null +++ b/bower_components/moment/locale/ar-sa.js @@ -0,0 +1,102 @@ +//! moment.js locale configuration +//! locale : Arabic Saudi Arabia (ar-sa) +//! author : Suhail Alkowaileet : https://github.com/xsoh + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' + }, numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' + }; + + var ar_sa = moment.defineLocale('ar-sa', { + months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D MMMM YYYY LT' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + 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, '،'); + }, + 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. + } + }); + + return ar_sa; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ar-tn.js b/bower_components/moment/locale/ar-tn.js new file mode 100644 index 0000000..ccf82cd --- /dev/null +++ b/bower_components/moment/locale/ar-tn.js @@ -0,0 +1,56 @@ +//! moment.js locale configuration +//! locale : Tunisian Arabic (ar-tn) + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ar_tn = moment.defineLocale('ar-tn', { + months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat: { + LT: 'HH:mm', + LTS: 'LT:ss', + 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: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return ar_tn; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ar.js b/bower_components/moment/locale/ar.js new file mode 100644 index 0000000..d08c983 --- /dev/null +++ b/bower_components/moment/locale/ar.js @@ -0,0 +1,135 @@ +//! moment.js locale configuration +//! Locale: Arabic (ar) +//! Author: Abdel Said: https://github.com/abdelsaid +//! Changes in months, weekdays: Ahmed Elkhatib +//! Native plural forms: forabi https://github.com/forabi + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' + }, numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' + }, pluralForm = function (n) { + return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5; + }, plurals = { + s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'], + m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'], + h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'], + d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'], + M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'], + y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام'] + }, pluralize = function (u) { + return function (number, withoutSuffix, string, isFuture) { + var f = pluralForm(number), + str = plurals[u][pluralForm(number)]; + if (f === 2) { + str = str[withoutSuffix ? 0 : 1]; + } + return str.replace(/%d/i, number); + }; + }, months = [ + 'كانون الثاني يناير', + 'شباط فبراير', + 'آذار مارس', + 'نيسان أبريل', + 'أيار مايو', + 'حزيران يونيو', + 'تموز يوليو', + 'آب أغسطس', + 'أيلول سبتمبر', + 'تشرين الأول أكتوبر', + 'تشرين الثاني نوفمبر', + 'كانون الأول ديسمبر' + ]; + + var ar = moment.defineLocale('ar', { + months : months, + monthsShort : months, + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'D/\u200FM/\u200FYYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D MMMM YYYY LT' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + 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 : pluralize('s'), + m : pluralize('m'), + mm : pluralize('m'), + h : pluralize('h'), + hh : pluralize('h'), + d : pluralize('d'), + dd : pluralize('d'), + M : pluralize('M'), + MM : pluralize('M'), + y : pluralize('y'), + yy : pluralize('y') + }, + preparse: function (string) { + return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { + return numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }).replace(/,/g, '،'); + }, + 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. + } + }); + + return ar; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/az.js b/bower_components/moment/locale/az.js new file mode 100644 index 0000000..6c17574 --- /dev/null +++ b/bower_components/moment/locale/az.js @@ -0,0 +1,103 @@ +//! moment.js locale configuration +//! locale : azerbaijani (az) +//! author : topchiyev : https://github.com/topchiyev + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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 az = moment.defineLocale('az', { + months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'), + monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'), + weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'), + weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'), + weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : '[sabah saat] LT', + nextWeek : '[gələn həftə] dddd [saat] LT', + lastDay : '[dünən] LT', + lastWeek : '[keçən həftə] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s sonra', + past : '%s əvvəl', + s : 'birneçə saniyyə', + m : 'bir dəqiqə', + mm : '%d dəqiqə', + h : 'bir saat', + hh : '%d saat', + d : 'bir gün', + dd : '%d gün', + M : 'bir ay', + MM : '%d ay', + y : 'bir il', + yy : '%d il' + }, + meridiemParse: /gecə|səhər|gündüz|axşam/, + isPM : function (input) { + return /^(gündüz|axşam)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'gecə'; + } else if (hour < 12) { + return 'səhər'; + } else if (hour < 17) { + return 'gündüz'; + } else { + return 'axşam'; + } + }, + ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/, + 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. + } + }); + + return az; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/be.js b/bower_components/moment/locale/be.js new file mode 100644 index 0000000..7ca287e --- /dev/null +++ b/bower_components/moment/locale/be.js @@ -0,0 +1,146 @@ +//! moment.js locale configuration +//! locale : belarusian (be) +//! author : Dmitry Demidov : https://github.com/demidov91 +//! author: Praleska: http://praleska.pro/ +//! Author : Menelion Elensúle : https://github.com/Oire + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін', + 'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін', + '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]?(\[[^\[\]]*\]|\s+)+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()]; + } + + var be = moment.defineLocale('be', { + months : monthsCaseReplace, + monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'), + weekdays : weekdaysCaseReplace, + weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 '[У] dddd [ў] LT'; + }, + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return '[У мінулую] dddd [ў] LT'; + case 1: + case 2: + case 4: + return '[У мінулы] dddd [ў] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'праз %s', + past : '%s таму', + s : 'некалькі секунд', + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : relativeTimeWithPlural, + hh : relativeTimeWithPlural, + d : 'дзень', + dd : relativeTimeWithPlural, + M : 'месяц', + MM : relativeTimeWithPlural, + y : 'год', + yy : relativeTimeWithPlural + }, + meridiemParse: /ночы|раніцы|дня|вечара/, + isPM : function (input) { + return /^(дня|вечара)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночы'; + } else if (hour < 12) { + return 'раніцы'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечара'; + } + }, + ordinalParse: /\d{1,2}-(і|ы|га)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : 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. + } + }); + + return be; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/bg.js b/bower_components/moment/locale/bg.js new file mode 100644 index 0000000..af66834 --- /dev/null +++ b/bower_components/moment/locale/bg.js @@ -0,0 +1,89 @@ +//! moment.js locale configuration +//! locale : bulgarian (bg) +//! author : Krasen Borisov : https://github.com/kraz + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var bg = moment.defineLocale('bg', { + months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'), + weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + 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 години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + 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. + } + }); + + return bg; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/bn.js b/bower_components/moment/locale/bn.js new file mode 100644 index 0000000..515a6f1 --- /dev/null +++ b/bower_components/moment/locale/bn.js @@ -0,0 +1,112 @@ +//! moment.js locale configuration +//! locale : Bengali (bn) +//! author : Kaushik Gandhi : https://github.com/kaushikgandhi + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '১', + '2': '২', + '3': '৩', + '4': '৪', + '5': '৫', + '6': '৬', + '7': '৭', + '8': '৮', + '9': '৯', + '0': '০' + }, + numberMap = { + '১': '1', + '২': '2', + '৩': '3', + '৪': '4', + '৫': '5', + '৬': '6', + '৭': '7', + '৮': '8', + '৯': '9', + '০': '0' + }; + + var bn = moment.defineLocale('bn', { + months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'), + monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split('_'), + weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রুবার_শনিবার'.split('_'), + weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্রু_শনি'.split('_'), + weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'), + longDateFormat : { + LT : 'A h:mm সময়', + LTS : 'A h:mm:ss সময়', + 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]; + }); + }, + meridiemParse: /রাত|শকাল|দুপুর|বিকেল|রাত/, + isPM: function (input) { + return /^(দুপুর|বিকেল|রাত)$/.test(input); + }, + //Bengali is a vast language its spoken + //in different forms in various parts of the world. + //I have just generalized with most common one used + 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. + } + }); + + return bn; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/bo.js b/bower_components/moment/locale/bo.js new file mode 100644 index 0000000..5bcfd9a --- /dev/null +++ b/bower_components/moment/locale/bo.js @@ -0,0 +1,109 @@ +//! moment.js locale configuration +//! locale : tibetan (bo) +//! author : Thupten N. Chakrishar : https://github.com/vajradog + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '༡', + '2': '༢', + '3': '༣', + '4': '༤', + '5': '༥', + '6': '༦', + '7': '༧', + '8': '༨', + '9': '༩', + '0': '༠' + }, + numberMap = { + '༡': '1', + '༢': '2', + '༣': '3', + '༤': '4', + '༥': '5', + '༦': '6', + '༧': '7', + '༨': '8', + '༩': '9', + '༠': '0' + }; + + var bo = moment.defineLocale('bo', { + months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'), + weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + longDateFormat : { + LT : 'A h:mm', + LTS : 'LT:ss', + 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 : '[བདུན་ཕྲག་རྗེས་མ], 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]; + }); + }, + meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/, + isPM: function (input) { + return /^(ཉིན་གུང|དགོང་དག|མཚན་མོ)$/.test(input); + }, + 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. + } + }); + + return bo; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/br.js b/bower_components/moment/locale/br.js new file mode 100644 index 0000000..a08280c --- /dev/null +++ b/bower_components/moment/locale/br.js @@ -0,0 +1,106 @@ +//! moment.js locale configuration +//! locale : breton (br) +//! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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); + } + + var br = moment.defineLocale('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', + LTS : 'h[e]mm:ss 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 + }, + ordinalParse: /\d{1,2}(añ|vet)/, + 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. + } + }); + + return br; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/bs.js b/bower_components/moment/locale/bs.js new file mode 100644 index 0000000..57139cc --- /dev/null +++ b/bower_components/moment/locale/bs.js @@ -0,0 +1,140 @@ +//! moment.js locale configuration +//! locale : bosnian (bs) +//! author : Nedim Cholich : https://github.com/frontyard +//! based on (hr) translation by Bojan Marković + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } + } + + var bs = moment.defineLocale('bs', { + months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'), + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : translate, + mm : translate, + h : translate, + hh : translate, + d : 'dan', + dd : translate, + M : 'mjesec', + MM : translate, + y : 'godinu', + yy : translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return bs; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ca.js b/bower_components/moment/locale/ca.js new file mode 100644 index 0000000..11cce50 --- /dev/null +++ b/bower_components/moment/locale/ca.js @@ -0,0 +1,78 @@ +//! moment.js locale configuration +//! locale : catalan (ca) +//! author : Juan G. Hurtado : https://github.com/juanghurtado + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ca = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(r|n|t|è|a)/, + ordinal : function (number, period) { + var output = (number === 1) ? 'r' : + (number === 2) ? 'n' : + (number === 3) ? 'r' : + (number === 4) ? 't' : 'è'; + if (period === 'w' || period === 'W') { + output = 'a'; + } + 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. + } + }); + + return ca; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/cs.js b/bower_components/moment/locale/cs.js new file mode 100644 index 0000000..0d8789d --- /dev/null +++ b/bower_components/moment/locale/cs.js @@ -0,0 +1,156 @@ +//! moment.js locale configuration +//! locale : czech (cs) +//! author : petrbela : https://github.com/petrbela + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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 sekund' : 'pár sekundami'; + 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; + } + } + + var cs = moment.defineLocale('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', + LTS : 'LT:ss', + 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 + }, + ordinalParse : /\d{1,2}\./, + 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. + } + }); + + return cs; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/cv.js b/bower_components/moment/locale/cv.js new file mode 100644 index 0000000..d01acab --- /dev/null +++ b/bower_components/moment/locale/cv.js @@ -0,0 +1,62 @@ +//! moment.js locale configuration +//! locale : chuvash (cv) +//! author : Anatoly Mironov : https://github.com/mirontoli + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var cv = moment.defineLocale('cv', { + months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'), + monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'), + weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'), + weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'), + weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 ҫул' + }, + ordinalParse: /\d{1,2}-мӗш/, + 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. + } + }); + + return cv; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/cy.js b/bower_components/moment/locale/cy.js new file mode 100644 index 0000000..e639124 --- /dev/null +++ b/bower_components/moment/locale/cy.js @@ -0,0 +1,78 @@ +//! moment.js locale configuration +//! locale : Welsh (cy) +//! author : Robert Allen + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var cy = moment.defineLocale('cy', { + months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'), + monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'), + weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'), + weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'), + weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'), + // time formats are the same as en-gb + longDateFormat: { + LT: 'HH:mm', + LTS : 'LT:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY LT', + LLLL: 'dddd, D MMMM YYYY LT' + }, + calendar: { + sameDay: '[Heddiw am] LT', + nextDay: '[Yfory am] LT', + nextWeek: 'dddd [am] LT', + lastDay: '[Ddoe am] LT', + lastWeek: 'dddd [diwethaf am] LT', + sameElse: 'L' + }, + relativeTime: { + future: 'mewn %s', + past: '%s yn ôl', + s: 'ychydig eiliadau', + m: 'munud', + mm: '%d munud', + h: 'awr', + hh: '%d awr', + d: 'diwrnod', + dd: '%d diwrnod', + M: 'mis', + MM: '%d mis', + y: 'blwyddyn', + yy: '%d flynedd' + }, + ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/, + // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh + ordinal: function (number) { + var b = number, + output = '', + lookup = [ + '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed + 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed + ]; + if (b > 20) { + if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) { + output = 'fed'; // not 30ain, 70ain or 90ain + } else { + output = 'ain'; + } + } else if (b > 0) { + output = lookup[b]; + } + 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. + } + }); + + return cy; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/da.js b/bower_components/moment/locale/da.js new file mode 100644 index 0000000..9a99381 --- /dev/null +++ b/bower_components/moment/locale/da.js @@ -0,0 +1,59 @@ +//! moment.js locale configuration +//! locale : danish (da) +//! author : Ulrik Nielsen : https://github.com/mrbase + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var da = moment.defineLocale('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', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd [d.] 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' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return da; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/de-at.js b/bower_components/moment/locale/de-at.js new file mode 100644 index 0000000..5309601 --- /dev/null +++ b/bower_components/moment/locale/de-at.js @@ -0,0 +1,75 @@ +//! moment.js locale configuration +//! locale : austrian german (de-at) +//! author : lluchs : https://github.com/lluchs +//! author: Menelion Elensúle: https://github.com/Oire +//! author : Martin Groller : https://github.com/MadMG + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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]; + } + + var de_at = moment.defineLocale('de-at', { + months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort : 'Jän._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: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay: '[Heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[Morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[Gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + 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 + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return de_at; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/de.js b/bower_components/moment/locale/de.js new file mode 100644 index 0000000..30a9b1e --- /dev/null +++ b/bower_components/moment/locale/de.js @@ -0,0 +1,74 @@ +//! moment.js locale configuration +//! locale : german (de) +//! author : lluchs : https://github.com/lluchs +//! author: Menelion Elensúle: https://github.com/Oire + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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]; + } + + var de = moment.defineLocale('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: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay: '[Heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[Morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[Gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + 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 + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return de; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/el.js b/bower_components/moment/locale/el.js new file mode 100644 index 0000000..d185642 --- /dev/null +++ b/bower_components/moment/locale/el.js @@ -0,0 +1,93 @@ +//! moment.js locale configuration +//! locale : modern greek (el) +//! author : Aggelos Karalias : https://github.com/mehiel + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var el = moment.defineLocale('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 ? 'πμ' : 'ΠΜ'; + } + }, + isPM : function (input) { + return ((input + '').toLowerCase()[0] === 'μ'); + }, + meridiemParse : /[ΠΜ]\.?Μ?\.?/i, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss 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 : function () { + switch (this.day()) { + case 6: + return '[το προηγούμενο] dddd [{}] LT'; + default: + return '[την προηγούμενη] dddd [{}] LT'; + } + }, + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendarEl[key], + hours = mom && mom.hours(); + if (typeof output === 'function') { + output = output.apply(mom); + } + 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 χρόνια' + }, + ordinalParse: /\d{1,2}η/, + ordinal: '%dη', + 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. + } + }); + + return el; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/en-au.js b/bower_components/moment/locale/en-au.js new file mode 100644 index 0000000..9a358e5 --- /dev/null +++ b/bower_components/moment/locale/en-au.js @@ -0,0 +1,65 @@ +//! moment.js locale configuration +//! locale : australian english (en-au) + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var en_au = moment.defineLocale('en-au', { + 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', + LTS : 'h:mm:ss 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' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + 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. + } + }); + + return en_au; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/en-ca.js b/bower_components/moment/locale/en-ca.js new file mode 100644 index 0000000..e0aaf01 --- /dev/null +++ b/bower_components/moment/locale/en-ca.js @@ -0,0 +1,62 @@ +//! moment.js locale configuration +//! locale : canadian english (en-ca) +//! author : Jonathan Abourbih : https://github.com/jonbca + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var en_ca = moment.defineLocale('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', + LTS : 'h:mm:ss 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' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + 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; + } + }); + + return en_ca; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/en-gb.js b/bower_components/moment/locale/en-gb.js new file mode 100644 index 0000000..e9eeace --- /dev/null +++ b/bower_components/moment/locale/en-gb.js @@ -0,0 +1,66 @@ +//! moment.js locale configuration +//! locale : great britain english (en-gb) +//! author : Chris Gedrim : https://github.com/chrisgedrim + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var en_gb = moment.defineLocale('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', + LTS : 'HH:mm:ss', + 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' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + 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. + } + }); + + return en_gb; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/eo.js b/bower_components/moment/locale/eo.js new file mode 100644 index 0000000..d4c7908 --- /dev/null +++ b/bower_components/moment/locale/eo.js @@ -0,0 +1,72 @@ +//! moment.js locale configuration +//! locale : 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 (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var eo = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + meridiemParse: /[ap]\.t\.m/i, + isPM: function (input) { + return input.charAt(0).toLowerCase() === 'p'; + }, + 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' + }, + ordinalParse: /\d{1,2}a/, + 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. + } + }); + + return eo; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/es.js b/bower_components/moment/locale/es.js new file mode 100644 index 0000000..4349217 --- /dev/null +++ b/bower_components/moment/locale/es.js @@ -0,0 +1,78 @@ +//! moment.js locale configuration +//! locale : spanish (es) +//! author : Julio Napurí : https://github.com/julionc + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var monthsShortDot = 'Ene._Feb._Mar._Abr._May._Jun._Jul._Ago._Sep._Oct._Nov._Dic.'.split('_'), + monthsShort = 'Ene_Feb_Mar_Abr_May_Jun_Jul_Ago_Sep_Oct_Nov_Dic'.split('_'); + + var es = moment.defineLocale('es', { + months : 'Enero_Febrero_Marzo_Abril_Mayo_Junio_Julio_Agosto_Septiembre_Octubre_Noviembre_Diciembre'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShort[m.month()]; + } else { + return monthsShortDot[m.month()]; + } + }, + 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', + LTS : 'LT:ss', + 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' + }, + ordinalParse : /\d{1,2}º/, + 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. + } + }); + + return es; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/et.js b/bower_components/moment/locale/et.js new file mode 100644 index 0000000..8cadeb2 --- /dev/null +++ b/bower_components/moment/locale/et.js @@ -0,0 +1,79 @@ +//! moment.js locale configuration +//! locale : estonian (et) +//! author : Henry Kehlmann : https://github.com/madhenry +//! improvements : Illimar Tambek : https://github.com/ragulka + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'], + 'm' : ['ühe minuti', 'üks minut'], + 'mm': [number + ' minuti', number + ' minutit'], + 'h' : ['ühe tunni', 'tund aega', 'üks tund'], + 'hh': [number + ' tunni', number + ' tundi'], + 'd' : ['ühe päeva', 'üks päev'], + 'M' : ['kuu aja', 'kuu aega', 'üks kuu'], + 'MM': [number + ' kuu', number + ' kuud'], + 'y' : ['ühe aasta', 'aasta', 'üks aasta'], + 'yy': [number + ' aasta', number + ' aastat'] + }; + if (withoutSuffix) { + return format[key][2] ? format[key][2] : format[key][1]; + } + return isFuture ? format[key][0] : format[key][1]; + } + + var et = moment.defineLocale('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', + LTS : 'LT:ss', + 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 : processRelativeTime, + m : processRelativeTime, + mm : processRelativeTime, + h : processRelativeTime, + hh : processRelativeTime, + d : processRelativeTime, + dd : '%d päeva', + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return et; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/eu.js b/bower_components/moment/locale/eu.js new file mode 100644 index 0000000..c90391a --- /dev/null +++ b/bower_components/moment/locale/eu.js @@ -0,0 +1,63 @@ +//! moment.js locale configuration +//! locale : euskara (eu) +//! author : Eneko Illarramendi : https://github.com/eillarra + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var eu = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return eu; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/fa.js b/bower_components/moment/locale/fa.js new file mode 100644 index 0000000..9a5e512 --- /dev/null +++ b/bower_components/moment/locale/fa.js @@ -0,0 +1,104 @@ +//! moment.js locale configuration +//! locale : Persian (fa) +//! author : Ebrahim Byagowi : https://github.com/ebraminio + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '۱', + '2': '۲', + '3': '۳', + '4': '۴', + '5': '۵', + '6': '۶', + '7': '۷', + '8': '۸', + '9': '۹', + '0': '۰' + }, numberMap = { + '۱': '1', + '۲': '2', + '۳': '3', + '۴': '4', + '۵': '5', + '۶': '6', + '۷': '7', + '۸': '8', + '۹': '9', + '۰': '0' + }; + + var fa = moment.defineLocale('fa', { + months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd, D MMMM YYYY LT' + }, + meridiemParse: /قبل از ظهر|بعد از ظهر/, + isPM: function (input) { + return /بعد از ظهر/.test(input); + }, + 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, '،'); + }, + ordinalParse: /\d{1,2}م/, + 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. + } + }); + + return fa; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/fi.js b/bower_components/moment/locale/fi.js new file mode 100644 index 0000000..b402320 --- /dev/null +++ b/bower_components/moment/locale/fi.js @@ -0,0 +1,106 @@ +//! moment.js locale configuration +//! locale : finnish (fi) +//! author : Tarmo Aidantausta : https://github.com/bleadof + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '), + numbersFuture = [ + 'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden', + numbersPast[7], numbersPast[8], numbersPast[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 = verbalNumber(number, isFuture) + ' ' + result; + return result; + } + function verbalNumber(number, isFuture) { + return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number; + } + + var fi = moment.defineLocale('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', + LTS : 'HH.mm.ss', + 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 + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return fi; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/fo.js b/bower_components/moment/locale/fo.js new file mode 100644 index 0000000..734d078 --- /dev/null +++ b/bower_components/moment/locale/fo.js @@ -0,0 +1,59 @@ +//! moment.js locale configuration +//! locale : faroese (fo) +//! author : Ragnar Johannesen : https://github.com/ragnar123 + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var fo = moment.defineLocale('fo', { + months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), + weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'), + weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'), + weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D. MMMM, YYYY LT' + }, + calendar : { + sameDay : '[Í dag kl.] LT', + nextDay : '[Í morgin kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[Í gjár kl.] LT', + lastWeek : '[síðstu] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'um %s', + past : '%s síðani', + s : 'fá sekund', + m : 'ein minutt', + mm : '%d minuttir', + h : 'ein tími', + hh : '%d tímar', + d : 'ein dagur', + dd : '%d dagar', + M : 'ein mánaði', + MM : '%d mánaðir', + y : 'eitt ár', + yy : '%d ár' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return fo; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/fr-ca.js b/bower_components/moment/locale/fr-ca.js new file mode 100644 index 0000000..decc50c --- /dev/null +++ b/bower_components/moment/locale/fr-ca.js @@ -0,0 +1,57 @@ +//! moment.js locale configuration +//! locale : canadian french (fr-ca) +//! author : Jonathan Abourbih : https://github.com/jonbca + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var fr_ca = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(er|)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : ''); + } + }); + + return fr_ca; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/fr.js b/bower_components/moment/locale/fr.js new file mode 100644 index 0000000..c2f83ef --- /dev/null +++ b/bower_components/moment/locale/fr.js @@ -0,0 +1,61 @@ +//! moment.js locale configuration +//! locale : french (fr) +//! author : John Fischer : https://github.com/jfroffice + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var fr = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(er|)/, + 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. + } + }); + + return fr; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/fy.js b/bower_components/moment/locale/fy.js new file mode 100644 index 0000000..57380dd --- /dev/null +++ b/bower_components/moment/locale/fy.js @@ -0,0 +1,70 @@ +//! moment.js locale configuration +//! locale : frisian (fy) +//! author : Robin van der Vliet : https://github.com/robin0van0der0v + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_'), + monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'); + + var fy = moment.defineLocale('fy', { + months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShortWithoutDots[m.month()]; + } else { + return monthsShortWithDots[m.month()]; + } + }, + weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'), + weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'), + weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D MMMM YYYY LT' + }, + calendar : { + sameDay: '[hjoed om] LT', + nextDay: '[moarn om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[juster om] LT', + lastWeek: '[ôfrûne] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'oer %s', + past : '%s lyn', + s : 'in pear sekonden', + m : 'ien minút', + mm : '%d minuten', + h : 'ien oere', + hh : '%d oeren', + d : 'ien dei', + dd : '%d dagen', + M : 'ien moanne', + MM : '%d moannen', + y : 'ien jier', + yy : '%d jierren' + }, + ordinalParse: /\d{1,2}(ste|de)/, + 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. + } + }); + + return fy; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/gl.js b/bower_components/moment/locale/gl.js new file mode 100644 index 0000000..88f271e --- /dev/null +++ b/bower_components/moment/locale/gl.js @@ -0,0 +1,74 @@ +//! moment.js locale configuration +//! locale : galician (gl) +//! author : Juan G. Hurtado : https://github.com/juanghurtado + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var gl = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse : /\d{1,2}º/, + 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. + } + }); + + return gl; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/he.js b/bower_components/moment/locale/he.js new file mode 100644 index 0000000..19a3b87 --- /dev/null +++ b/bower_components/moment/locale/he.js @@ -0,0 +1,81 @@ +//! moment.js locale configuration +//! locale : Hebrew (he) +//! author : Tomer Cohen : https://github.com/tomer +//! author : Moshe Simantov : https://github.com/DevelopmentIL +//! author : Tal Ater : https://github.com/TalAter + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var he = moment.defineLocale('he', { + months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'), + monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'), + weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'), + weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'), + weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : function (number) { + if (number === 2) { + return 'שעתיים'; + } + return number + ' שעות'; + }, + d : 'יום', + dd : function (number) { + if (number === 2) { + return 'יומיים'; + } + return number + ' ימים'; + }, + M : 'חודש', + MM : function (number) { + if (number === 2) { + return 'חודשיים'; + } + return number + ' חודשים'; + }, + y : 'שנה', + yy : function (number) { + if (number === 2) { + return 'שנתיים'; + } else if (number % 10 === 0 && number !== 10) { + return number + ' שנה'; + } + return number + ' שנים'; + } + } + }); + + return he; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/hi.js b/bower_components/moment/locale/hi.js new file mode 100644 index 0000000..7177806 --- /dev/null +++ b/bower_components/moment/locale/hi.js @@ -0,0 +1,122 @@ +//! moment.js locale configuration +//! locale : hindi (hi) +//! author : Mayank Singhal : https://github.com/mayanksinghal + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var hi = moment.defineLocale('hi', { + months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'), + monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'), + weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm बजे', + LTS : 'A h:mm:ss बजे', + 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. + meridiemParse: /रात|सुबह|दोपहर|शाम/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सुबह') { + return hour; + } else if (meridiem === 'दोपहर') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'शाम') { + return hour + 12; + } + }, + 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. + } + }); + + return hi; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/hr.js b/bower_components/moment/locale/hr.js new file mode 100644 index 0000000..2c948e3 --- /dev/null +++ b/bower_components/moment/locale/hr.js @@ -0,0 +1,139 @@ +//! moment.js locale configuration +//! locale : hrvatski (hr) +//! author : Bojan Marković : https://github.com/bmarkovic + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } + } + + var hr = moment.defineLocale('hr', { + months : 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_'), + monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'), + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : translate, + mm : translate, + h : translate, + hh : translate, + d : 'dan', + dd : translate, + M : 'mjesec', + MM : translate, + y : 'godinu', + yy : translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return hr; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/hu.js b/bower_components/moment/locale/hu.js new file mode 100644 index 0000000..4a95c84 --- /dev/null +++ b/bower_components/moment/locale/hu.js @@ -0,0 +1,108 @@ +//! moment.js locale configuration +//! locale : hungarian (hu) +//! author : Adam Brunner : https://github.com/adambrunner + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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]'; + } + + var hu = moment.defineLocale('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 : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'), + weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + L : 'YYYY.MM.DD.', + LL : 'YYYY. MMMM D.', + LLL : 'YYYY. MMMM D., LT', + LLLL : 'YYYY. MMMM D., dddd LT' + }, + meridiemParse: /de|du/i, + isPM: function (input) { + return input.charAt(1).toLowerCase() === 'u'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower === true ? 'de' : 'DE'; + } else { + return isLower === true ? 'du' : 'DU'; + } + }, + 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 + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return hu; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/hy-am.js b/bower_components/moment/locale/hy-am.js new file mode 100644 index 0000000..08c5c75 --- /dev/null +++ b/bower_components/moment/locale/hy-am.js @@ -0,0 +1,110 @@ +//! moment.js locale configuration +//! locale : Armenian (hy-am) +//! author : Armendarabyan : https://github.com/armendarabyan + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function monthsCaseReplace(m, format) { + var months = { + 'nominative': 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_'), + 'accusative': 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_') + }, + nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; + } + function monthsShortCaseReplace(m, format) { + var monthsShort = 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'); + return monthsShort[m.month()]; + } + function weekdaysCaseReplace(m, format) { + var weekdays = 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'); + return weekdays[m.day()]; + } + + var hy_am = moment.defineLocale('hy-am', { + months : monthsCaseReplace, + monthsShort : monthsShortCaseReplace, + weekdays : weekdaysCaseReplace, + weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 'dddd [օրը ժամը] LT'; + }, + lastWeek: function () { + 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 տարի' + }, + meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/, + isPM: function (input) { + return /^(ցերեկվա|երեկոյան)$/.test(input); + }, + meridiem : function (hour) { + if (hour < 4) { + return 'գիշերվա'; + } else if (hour < 12) { + return 'առավոտվա'; + } else if (hour < 17) { + return 'ցերեկվա'; + } else { + return 'երեկոյան'; + } + }, + ordinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/, + ordinal: function (number, period) { + switch (period) { + case 'DDD': + case 'w': + case 'W': + case 'DDDo': + if (number === 1) { + return number + '-ին'; + } + 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. + } + }); + + return hy_am; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/id.js b/bower_components/moment/locale/id.js new file mode 100644 index 0000000..d9278bd --- /dev/null +++ b/bower_components/moment/locale/id.js @@ -0,0 +1,82 @@ +//! moment.js locale configuration +//! locale : 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 (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var id = moment.defineLocale('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', + LTS : 'LT.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] LT', + LLLL : 'dddd, D MMMM YYYY [pukul] LT' + }, + meridiemParse: /pagi|siang|sore|malam/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'siang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sore' || meridiem === 'malam') { + return hour + 12; + } + }, + 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. + } + }); + + return id; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/is.js b/bower_components/moment/locale/is.js new file mode 100644 index 0000000..3276712 --- /dev/null +++ b/bower_components/moment/locale/is.js @@ -0,0 +1,126 @@ +//! moment.js locale configuration +//! locale : icelandic (is) +//! author : Hinrik Örn Sigurðsson : https://github.com/hinrik + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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'); + } + } + + var is = moment.defineLocale('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', + LTS : 'LT:ss', + 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 + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return is; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/it.js b/bower_components/moment/locale/it.js new file mode 100644 index 0000000..84fe389 --- /dev/null +++ b/bower_components/moment/locale/it.js @@ -0,0 +1,69 @@ +//! moment.js locale configuration +//! locale : italian (it) +//! author : Lorenzo : https://github.com/aliem +//! author: Mattia Larentis: https://github.com/nostalgiaz + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var it = moment.defineLocale('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', + LTS : 'LT:ss', + 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: function () { + switch (this.day()) { + case 0: + return '[la scorsa] dddd [alle] LT'; + default: + return '[lo scorso] dddd [alle] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : function (s) { + return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s; + }, + past : '%s fa', + s : 'alcuni 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' + }, + ordinalParse : /\d{1,2}º/, + 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. + } + }); + + return it; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ja.js b/bower_components/moment/locale/ja.js new file mode 100644 index 0000000..de01577 --- /dev/null +++ b/bower_components/moment/locale/ja.js @@ -0,0 +1,64 @@ +//! moment.js locale configuration +//! locale : japanese (ja) +//! author : LI Long : https://github.com/baryon + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ja = moment.defineLocale('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分', + LTS : 'LTs秒', + L : 'YYYY/MM/DD', + LL : 'YYYY年M月D日', + LLL : 'YYYY年M月D日LT', + LLLL : 'YYYY年M月D日LT dddd' + }, + meridiemParse: /午前|午後/i, + isPM : function (input) { + return input === '午後'; + }, + 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年' + } + }); + + return ja; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/jv.js b/bower_components/moment/locale/jv.js new file mode 100644 index 0000000..e73ae19 --- /dev/null +++ b/bower_components/moment/locale/jv.js @@ -0,0 +1,82 @@ +//! moment.js locale configuration +//! locale : Boso Jowo (jv) +//! author : Rony Lantip : https://github.com/lantip +//! reference: http://jv.wikipedia.org/wiki/Basa_Jawa + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var jv = moment.defineLocale('jv', { + months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'), + weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'), + weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'), + weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'LT.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] LT', + LLLL : 'dddd, D MMMM YYYY [pukul] LT' + }, + meridiemParse: /enjing|siyang|sonten|ndalu/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'enjing') { + return hour; + } else if (meridiem === 'siyang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sonten' || meridiem === 'ndalu') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'enjing'; + } else if (hours < 15) { + return 'siyang'; + } else if (hours < 19) { + return 'sonten'; + } else { + return 'ndalu'; + } + }, + calendar : { + sameDay : '[Dinten puniko pukul] LT', + nextDay : '[Mbenjang pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kala wingi pukul] LT', + lastWeek : 'dddd [kepengker pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'wonten ing %s', + past : '%s ingkang kepengker', + s : 'sawetawis detik', + m : 'setunggal menit', + mm : '%d menit', + h : 'setunggal jam', + hh : '%d jam', + d : 'sedinten', + dd : '%d dinten', + M : 'sewulan', + MM : '%d wulan', + y : 'setaun', + yy : '%d taun' + }, + 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. + } + }); + + return jv; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ka.js b/bower_components/moment/locale/ka.js new file mode 100644 index 0000000..19bcb3a --- /dev/null +++ b/bower_components/moment/locale/ka.js @@ -0,0 +1,102 @@ +//! moment.js locale configuration +//! locale : Georgian (ka) +//! author : Irakli Janiashvili : https://github.com/irakli-janiashvili + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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()]; + } + + var ka = moment.defineLocale('ka', { + months : monthsCaseReplace, + monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'), + weekdays : weekdaysCaseReplace, + weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'), + weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss 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 წელი' + }, + ordinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/, + 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 + } + }); + + return ka; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/km.js b/bower_components/moment/locale/km.js new file mode 100644 index 0000000..d6f6c65 --- /dev/null +++ b/bower_components/moment/locale/km.js @@ -0,0 +1,57 @@ +//! moment.js locale configuration +//! locale : khmer (km) +//! author : Kruy Vanna : https://github.com/kruyvanna + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var km = moment.defineLocale('km', { + months: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + monthsShort: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + longDateFormat: { + LT: 'HH:mm', + LTS : 'LT:ss', + 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: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + return km; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ko.js b/bower_components/moment/locale/ko.js new file mode 100644 index 0000000..ded3714 --- /dev/null +++ b/bower_components/moment/locale/ko.js @@ -0,0 +1,67 @@ +//! moment.js locale configuration +//! locale : korean (ko) +//! +//! authors +//! +//! - Kyungwook, Park : https://github.com/kyungw00k +//! - Jeeeyul Lee <jeeeyul@gmail.com> + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ko = moment.defineLocale('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시 m분', + LTS : 'A h시 m분 s초', + L : 'YYYY.MM.DD', + LL : 'YYYY년 MMMM D일', + LLL : 'YYYY년 MMMM D일 LT', + LLLL : 'YYYY년 MMMM D일 dddd LT' + }, + 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년' + }, + ordinalParse : /\d{1,2}일/, + ordinal : '%d일', + meridiemParse : /오전|오후/, + isPM : function (token) { + return token === '오후'; + }, + meridiem : function (hour, minute, isUpper) { + return hour < 12 ? '오전' : '오후'; + } + }); + + return ko; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/lb.js b/bower_components/moment/locale/lb.js new file mode 100644 index 0000000..43f988a --- /dev/null +++ b/bower_components/moment/locale/lb.js @@ -0,0 +1,133 @@ +//! moment.js locale configuration +//! locale : Luxembourgish (lb) +//! author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eng Minutt', 'enger Minutt'], + 'h': ['eng Stonn', 'enger Stonn'], + 'd': ['een Dag', 'engem Dag'], + 'M': ['ee Mount', 'engem Mount'], + 'y': ['ee Joer', 'engem Joer'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; + } + function processFutureTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'a ' + string; + } + return 'an ' + string; + } + function processPastTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'viru ' + string; + } + return 'virun ' + string; + } + /** + * Returns true if the word before the given number loses the '-n' ending. + * e.g. 'an 10 Deeg' but 'a 5 Deeg' + * + * @param number {integer} + * @returns {boolean} + */ + function eifelerRegelAppliesToNumber(number) { + number = parseInt(number, 10); + if (isNaN(number)) { + return false; + } + if (number < 0) { + // Negative Number --> always true + return true; + } else if (number < 10) { + // Only 1 digit + if (4 <= number && number <= 7) { + return true; + } + return false; + } else if (number < 100) { + // 2 digits + var lastDigit = number % 10, firstDigit = number / 10; + if (lastDigit === 0) { + return eifelerRegelAppliesToNumber(firstDigit); + } + return eifelerRegelAppliesToNumber(lastDigit); + } else if (number < 10000) { + // 3 or 4 digits --> recursively check first digit + while (number >= 10) { + number = number / 10; + } + return eifelerRegelAppliesToNumber(number); + } else { + // Anything larger than 4 digits: recursively check first n-3 digits + number = number / 1000; + return eifelerRegelAppliesToNumber(number); + } + } + + var lb = moment.defineLocale('lb', { + months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'), + weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'), + weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'), + longDateFormat: { + LT: 'H:mm [Auer]', + LTS: 'H:mm:ss [Auer]', + L: 'DD.MM.YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY LT', + LLLL: 'dddd, D. MMMM YYYY LT' + }, + calendar: { + sameDay: '[Haut um] LT', + sameElse: 'L', + nextDay: '[Muer um] LT', + nextWeek: 'dddd [um] LT', + lastDay: '[Gëschter um] LT', + lastWeek: function () { + // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule + switch (this.day()) { + case 2: + case 4: + return '[Leschten] dddd [um] LT'; + default: + return '[Leschte] dddd [um] LT'; + } + } + }, + relativeTime : { + future : processFutureTime, + past : processPastTime, + s : 'e puer Sekonnen', + m : processRelativeTime, + mm : '%d Minutten', + h : processRelativeTime, + hh : '%d Stonnen', + d : processRelativeTime, + dd : '%d Deeg', + M : processRelativeTime, + MM : '%d Méint', + y : processRelativeTime, + yy : '%d Joer' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return lb; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/lt.js b/bower_components/moment/locale/lt.js new file mode 100644 index 0000000..8f0ef54 --- /dev/null +++ b/bower_components/moment/locale/lt.js @@ -0,0 +1,114 @@ +//! moment.js locale configuration +//! locale : Lithuanian (lt) +//! author : Mindaugas Mozūras : https://github.com/mmozuras + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var units = { + 'm' : 'minutė_minutės_minutę', + 'mm': 'minutės_minučių_minutes', + 'h' : 'valanda_valandos_valandą', + 'hh': 'valandos_valandų_valandas', + 'd' : 'diena_dienos_dieną', + 'dd': 'dienos_dienų_dienas', + 'M' : 'mėnuo_mėnesio_mėnesį', + 'MM': 'mėnesiai_mėnesių_mėnesius', + 'y' : 'metai_metų_metus', + 'yy': 'metai_metų_metus' + }, + weekDays = 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'); + function translateSeconds(number, withoutSuffix, key, isFuture) { + if (withoutSuffix) { + return 'kelios sekundės'; + } else { + return isFuture ? 'kelių sekundžių' : 'kelias sekundes'; + } + } + function translateSingular(number, withoutSuffix, key, isFuture) { + return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]); + } + function special(number) { + return number % 10 === 0 || (number > 10 && number < 20); + } + function forms(key) { + return units[key].split('_'); + } + function translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + if (number === 1) { + return result + translateSingular(number, withoutSuffix, key[0], isFuture); + } else if (withoutSuffix) { + return result + (special(number) ? forms(key)[1] : forms(key)[0]); + } else { + if (isFuture) { + return result + forms(key)[1]; + } else { + return result + (special(number) ? forms(key)[1] : forms(key)[2]); + } + } + } + function relativeWeekDay(moment, format) { + var nominative = format.indexOf('dddd HH:mm') === -1, + weekDay = weekDays[moment.day()]; + return nominative ? weekDay : weekDay.substring(0, weekDay.length - 2) + 'į'; + } + + var lt = moment.defineLocale('lt', { + months : 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'), + monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'), + weekdays : relativeWeekDay, + weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'), + weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'YYYY-MM-DD', + LL : 'YYYY [m.] MMMM D [d.]', + LLL : 'YYYY [m.] MMMM D [d.], LT [val.]', + LLLL : 'YYYY [m.] MMMM D [d.], dddd, LT [val.]', + l : 'YYYY-MM-DD', + ll : 'YYYY [m.] MMMM D [d.]', + lll : 'YYYY [m.] MMMM D [d.], LT [val.]', + llll : 'YYYY [m.] MMMM D [d.], ddd, LT [val.]' + }, + calendar : { + sameDay : '[Šiandien] LT', + nextDay : '[Rytoj] LT', + nextWeek : 'dddd LT', + lastDay : '[Vakar] LT', + lastWeek : '[Praėjusį] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : 'po %s', + past : 'prieš %s', + s : translateSeconds, + m : translateSingular, + mm : translate, + h : translateSingular, + hh : translate, + d : translateSingular, + dd : translate, + M : translateSingular, + MM : translate, + y : translateSingular, + yy : translate + }, + ordinalParse: /\d{1,2}-oji/, + ordinal : function (number) { + return number + '-oji'; + }, + 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. + } + }); + + return lt; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/lv.js b/bower_components/moment/locale/lv.js new file mode 100644 index 0000000..ad1cc0a --- /dev/null +++ b/bower_components/moment/locale/lv.js @@ -0,0 +1,95 @@ +//! moment.js locale configuration +//! locale : latvian (lv) +//! author : Kristaps Karlsons : https://github.com/skakri +//! author : Jānis Elmeris : https://github.com/JanisE + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var units = { + 'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'h': 'stundas_stundām_stunda_stundas'.split('_'), + 'hh': 'stundas_stundām_stunda_stundas'.split('_'), + 'd': 'dienas_dienām_diena_dienas'.split('_'), + 'dd': 'dienas_dienām_diena_dienas'.split('_'), + 'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'y': 'gada_gadiem_gads_gadi'.split('_'), + 'yy': 'gada_gadiem_gads_gadi'.split('_') + }; + /** + * @param withoutSuffix boolean true = a length of time; false = before/after a period of time. + */ + function format(forms, number, withoutSuffix) { + if (withoutSuffix) { + // E.g. "21 minūte", "3 minūtes". + return number % 10 === 1 && number !== 11 ? forms[2] : forms[3]; + } else { + // E.g. "21 minūtes" as in "pēc 21 minūtes". + // E.g. "3 minūtēm" as in "pēc 3 minūtēm". + return number % 10 === 1 && number !== 11 ? forms[0] : forms[1]; + } + } + function relativeTimeWithPlural(number, withoutSuffix, key) { + return number + ' ' + format(units[key], number, withoutSuffix); + } + function relativeTimeWithSingular(number, withoutSuffix, key) { + return format(units[key], number, withoutSuffix); + } + function relativeSeconds(number, withoutSuffix) { + return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm'; + } + + var lv = moment.defineLocale('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', + LTS : 'LT:ss', + 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 : 'pēc %s', + past : 'pirms %s', + s : relativeSeconds, + m : relativeTimeWithSingular, + mm : relativeTimeWithPlural, + h : relativeTimeWithSingular, + hh : relativeTimeWithPlural, + d : relativeTimeWithSingular, + dd : relativeTimeWithPlural, + M : relativeTimeWithSingular, + MM : relativeTimeWithPlural, + y : relativeTimeWithSingular, + yy : relativeTimeWithPlural + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return lv; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/me.js b/bower_components/moment/locale/me.js new file mode 100644 index 0000000..37bc78c --- /dev/null +++ b/bower_components/moment/locale/me.js @@ -0,0 +1,108 @@ +//! moment.js locale configuration +//! locale : Montenegrin (me) +//! author : Miodrag Nikač <miodrag@restartit.me> : https://github.com/miodragnikac + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jednog minuta'], + mm: ['minut', 'minuta', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mjesec', 'mjeseca', 'mjeseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var me = moment.defineLocale('me', { + months: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'], + monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'], + weekdays: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'], + weekdaysShort: ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'], + weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'], + longDateFormat: { + LT: 'H:mm', + LTS : 'LT:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY LT', + LLLL: 'dddd, D. MMMM YYYY LT' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sjutra u] LT', + + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedjelje] [u] LT', + '[prošlog] [ponedjeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srijede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'nekoliko sekundi', + m : translator.translate, + mm : translator.translate, + h : translator.translate, + hh : translator.translate, + d : 'dan', + dd : translator.translate, + M : 'mjesec', + MM : translator.translate, + y : 'godinu', + yy : translator.translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return me; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/mk.js b/bower_components/moment/locale/mk.js new file mode 100644 index 0000000..f04826f --- /dev/null +++ b/bower_components/moment/locale/mk.js @@ -0,0 +1,89 @@ +//! moment.js locale configuration +//! locale : macedonian (mk) +//! author : Borislav Mickov : https://github.com/B0k0 + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var mk = moment.defineLocale('mk', { + months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'), + weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'), + weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + 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 години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + 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. + } + }); + + return mk; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ml.js b/bower_components/moment/locale/ml.js new file mode 100644 index 0000000..fe59373 --- /dev/null +++ b/bower_components/moment/locale/ml.js @@ -0,0 +1,70 @@ +//! moment.js locale configuration +//! locale : malayalam (ml) +//! author : Floyd Pink : https://github.com/floydpink + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ml = moment.defineLocale('ml', { + months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'), + monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'), + weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'), + weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'), + weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'), + longDateFormat : { + LT : 'A h:mm -നു', + LTS : 'A h:mm:ss -നു', + 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 വർഷം' + }, + meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i, + isPM : function (input) { + return /^(ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'രാത്രി'; + } else if (hour < 12) { + return 'രാവിലെ'; + } else if (hour < 17) { + return 'ഉച്ച കഴിഞ്ഞ്'; + } else if (hour < 20) { + return 'വൈകുന്നേരം'; + } else { + return 'രാത്രി'; + } + } + }); + + return ml; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/mr.js b/bower_components/moment/locale/mr.js new file mode 100644 index 0000000..9072d69 --- /dev/null +++ b/bower_components/moment/locale/mr.js @@ -0,0 +1,120 @@ +//! moment.js locale configuration +//! locale : Marathi (mr) +//! author : Harshad Kale : https://github.com/kalehv + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var mr = moment.defineLocale('mr', { + months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'), + monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'), + weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm वाजता', + LTS : 'A h:mm:ss वाजता', + 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]; + }); + }, + meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात्री') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सकाळी') { + return hour; + } else if (meridiem === 'दुपारी') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'सायंकाळी') { + return hour + 12; + } + }, + 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. + } + }); + + return mr; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ms-my.js b/bower_components/moment/locale/ms-my.js new file mode 100644 index 0000000..d1ea5a2 --- /dev/null +++ b/bower_components/moment/locale/ms-my.js @@ -0,0 +1,81 @@ +//! moment.js locale configuration +//! locale : Bahasa Malaysia (ms-MY) +//! author : Weldan Jamili : https://github.com/weldan + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ms_my = moment.defineLocale('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', + LTS : 'LT.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] LT', + LLLL : 'dddd, D MMMM YYYY [pukul] LT' + }, + meridiemParse: /pagi|tengahari|petang|malam/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'tengahari') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'petang' || meridiem === 'malam') { + return hour + 12; + } + }, + 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. + } + }); + + return ms_my; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/my.js b/bower_components/moment/locale/my.js new file mode 100644 index 0000000..e50972b --- /dev/null +++ b/bower_components/moment/locale/my.js @@ -0,0 +1,92 @@ +//! moment.js locale configuration +//! locale : Burmese (my) +//! author : Squar team, mysquar.com + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '၁', + '2': '၂', + '3': '၃', + '4': '၄', + '5': '၅', + '6': '၆', + '7': '၇', + '8': '၈', + '9': '၉', + '0': '၀' + }, numberMap = { + '၁': '1', + '၂': '2', + '၃': '3', + '၄': '4', + '၅': '5', + '၆': '6', + '၇': '7', + '၈': '8', + '၉': '9', + '၀': '0' + }; + + var my = moment.defineLocale('my', { + months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'), + monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'), + weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'), + weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + + longDateFormat: { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + 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]; + }); + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 1st is the first week of the year. + } + }); + + return my; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/nb.js b/bower_components/moment/locale/nb.js new file mode 100644 index 0000000..6ab39c4 --- /dev/null +++ b/bower_components/moment/locale/nb.js @@ -0,0 +1,60 @@ +//! moment.js locale configuration +//! locale : norwegian bokmål (nb) +//! authors : Espen Hovlandsdal : https://github.com/rexxars +//! Sigurd Gartmann : https://github.com/sigurdga + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var nb = moment.defineLocale('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_tirs_ons_tors_fre_lør'.split('_'), + weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), + longDateFormat : { + LT : 'H.mm', + LTS : 'LT.ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] LT', + LLLL : 'dddd D. MMMM YYYY [kl.] LT' + }, + calendar : { + sameDay: '[i dag kl.] LT', + nextDay: '[i morgen kl.] LT', + nextWeek: 'dddd [kl.] LT', + lastDay: '[i går kl.] LT', + lastWeek: '[forrige] dddd [kl.] 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' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return nb; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ne.js b/bower_components/moment/locale/ne.js new file mode 100644 index 0000000..dfbe878 --- /dev/null +++ b/bower_components/moment/locale/ne.js @@ -0,0 +1,122 @@ +//! moment.js locale configuration +//! locale : nepali/nepalese +//! author : suvash : https://github.com/suvash + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var ne = moment.defineLocale('ne', { + months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'), + monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'), + weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'), + weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'), + weekdaysMin : 'आइ._सो._मङ्_बु._बि._शु._श.'.split('_'), + longDateFormat : { + LT : 'Aको h:mm बजे', + LTS : 'Aको h:mm:ss बजे', + 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]; + }); + }, + meridiemParse: /राती|बिहान|दिउँसो|बेलुका|साँझ|राती/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'राती') { + return hour < 3 ? hour : hour + 12; + } else if (meridiem === 'बिहान') { + return hour; + } else if (meridiem === 'दिउँसो') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'बेलुका' || meridiem === 'साँझ') { + return hour + 12; + } + }, + 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. + } + }); + + return ne; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/nl.js b/bower_components/moment/locale/nl.js new file mode 100644 index 0000000..7b5f3a2 --- /dev/null +++ b/bower_components/moment/locale/nl.js @@ -0,0 +1,70 @@ +//! moment.js locale configuration +//! locale : dutch (nl) +//! author : Joris Röling : https://github.com/jjupiter + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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('_'); + + var nl = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(ste|de)/, + 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. + } + }); + + return nl; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/nn.js b/bower_components/moment/locale/nn.js new file mode 100644 index 0000000..74424cd --- /dev/null +++ b/bower_components/moment/locale/nn.js @@ -0,0 +1,59 @@ +//! moment.js locale configuration +//! locale : norwegian nynorsk (nn) +//! author : https://github.com/mechuwind + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var nn = moment.defineLocale('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', + LTS : 'LT:ss', + L : 'DD.MM.YYYY', + 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åande] dddd [klokka] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : 'for %s sidan', + s : 'nokre sekund', + m : 'eit minutt', + mm : '%d minutt', + h : 'ein time', + hh : '%d timar', + d : 'ein dag', + dd : '%d dagar', + M : 'ein månad', + MM : '%d månader', + y : 'eit år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return nn; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/pl.js b/bower_components/moment/locale/pl.js new file mode 100644 index 0000000..075c102 --- /dev/null +++ b/bower_components/moment/locale/pl.js @@ -0,0 +1,104 @@ +//! moment.js locale configuration +//! locale : polish (pl) +//! author : Rafal Hirsz : https://github.com/evoL + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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) % 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'); + } + } + + var pl = moment.defineLocale('pl', { + months : function (momentToFormat, format) { + if (format === '') { + // Hack: if format empty we know this is used to generate + // RegExp by moment. Give then back both valid forms of months + // in RegExp ready format. + return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')'; + } else 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', + LTS : 'LT:ss', + 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 + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return pl; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/pt-br.js b/bower_components/moment/locale/pt-br.js new file mode 100644 index 0000000..47948a3 --- /dev/null +++ b/bower_components/moment/locale/pt-br.js @@ -0,0 +1,59 @@ +//! moment.js locale configuration +//! locale : brazilian portuguese (pt-br) +//! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var pt_br = moment.defineLocale('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', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY [às] LT', + LLLL : 'dddd, D [de] MMMM [de] YYYY [às] 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' + }, + ordinalParse: /\d{1,2}º/, + ordinal : '%dº' + }); + + return pt_br; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/pt.js b/bower_components/moment/locale/pt.js new file mode 100644 index 0000000..1a332e2 --- /dev/null +++ b/bower_components/moment/locale/pt.js @@ -0,0 +1,63 @@ +//! moment.js locale configuration +//! locale : portuguese (pt) +//! author : Jefferson : https://github.com/jalex79 + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var pt = moment.defineLocale('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', + LTS : 'LT:ss', + 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 : 'há %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' + }, + ordinalParse: /\d{1,2}º/, + 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. + } + }); + + return pt; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ro.js b/bower_components/moment/locale/ro.js new file mode 100644 index 0000000..576798b --- /dev/null +++ b/bower_components/moment/locale/ro.js @@ -0,0 +1,73 @@ +//! moment.js locale configuration +//! locale : romanian (ro) +//! author : Vlad Gurdiga : https://github.com/gurdiga +//! author : Valentin Agachi : https://github.com/avaly + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': 'minute', + 'hh': 'ore', + 'dd': 'zile', + 'MM': 'luni', + 'yy': 'ani' + }, + separator = ' '; + if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) { + separator = ' de '; + } + return number + separator + format[key]; + } + + var ro = moment.defineLocale('ro', { + months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'), + monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._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', + LTS : 'LT:ss', + 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 : relativeTimeWithPlural, + h : 'o oră', + hh : relativeTimeWithPlural, + d : 'o zi', + dd : relativeTimeWithPlural, + M : 'o lună', + MM : relativeTimeWithPlural, + y : 'un an', + yy : relativeTimeWithPlural + }, + 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. + } + }); + + return ro; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ru.js b/bower_components/moment/locale/ru.js new file mode 100644 index 0000000..77efbe4 --- /dev/null +++ b/bower_components/moment/locale/ru.js @@ -0,0 +1,163 @@ +//! moment.js locale configuration +//! locale : russian (ru) +//! author : Viktorminator : https://github.com/Viktorminator +//! Author : Menelion Elensúle : https://github.com/Oire + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут', + '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]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; + } + function monthsShortCaseReplace(m, format) { + var monthsShort = { + 'nominative': 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'), + 'accusative': 'янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек'.split('_') + }, + nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return monthsShort[nounCase][m.month()]; + } + function weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), + 'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_') + }, + nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/).test(format) ? + 'accusative' : + 'nominative'; + return weekdays[nounCase][m.day()]; + } + + var ru = moment.defineLocale('ru', { + months : monthsCaseReplace, + monthsShort : monthsShortCaseReplace, + weekdays : weekdaysCaseReplace, + weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + monthsParse : [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[й|я]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i], + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 (now) { + if (now.week() !== this.week()) { + 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'; + } + } else { + if (this.day() === 2) { + return '[Во] dddd [в] LT'; + } else { + 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 + }, + meridiemParse: /ночи|утра|дня|вечера/i, + isPM : function (input) { + return /^(дня|вечера)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночи'; + } else if (hour < 12) { + return 'утра'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечера'; + } + }, + ordinalParse: /\d{1,2}-(й|го|я)/, + 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. + } + }); + + return ru; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/si.js b/bower_components/moment/locale/si.js new file mode 100644 index 0000000..e831f25 --- /dev/null +++ b/bower_components/moment/locale/si.js @@ -0,0 +1,64 @@ +//! moment.js locale configuration +//! locale : Sinhalese (si) +//! author : Sampath Sitinamaluwa : https://github.com/sampathsris + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var si = moment.defineLocale('si', { + months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'), + monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'), + weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'), + weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්රහ_සිකු_සෙන'.split('_'), + weekdaysMin : 'ඉ_ස_අ_බ_බ්ර_සි_සෙ'.split('_'), + longDateFormat : { + LT : 'a h:mm', + LTS : 'a h:mm:ss', + L : 'YYYY/MM/DD', + LL : 'YYYY MMMM D', + LLL : 'YYYY MMMM D, LT', + LLLL : 'YYYY MMMM D [වැනි] dddd, LTS' + }, + 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' + }, + ordinalParse: /\d{1,2} වැනි/, + ordinal : function (number) { + return number + ' වැනි'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'ප.ව.' : 'පස් වරු'; + } else { + return isLower ? 'පෙ.ව.' : 'පෙර වරු'; + } + } + }); + + return si; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/sk.js b/bower_components/moment/locale/sk.js new file mode 100644 index 0000000..f48a560 --- /dev/null +++ b/bower_components/moment/locale/sk.js @@ -0,0 +1,157 @@ +//! moment.js locale configuration +//! locale : slovak (sk) +//! author : Martin Minka : https://github.com/k2s +//! based on work of petrbela : https://github.com/petrbela + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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; + } + } + + var sk = moment.defineLocale('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', + LTS : 'LT:ss', + 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 + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return sk; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/sl.js b/bower_components/moment/locale/sl.js new file mode 100644 index 0000000..00c079b --- /dev/null +++ b/bower_components/moment/locale/sl.js @@ -0,0 +1,159 @@ +//! moment.js locale configuration +//! locale : slovenian (sl) +//! author : Robert Sedovšek : https://github.com/sedovsek + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + function processRelativeTime(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami'; + case 'm': + return withoutSuffix ? 'ena minuta' : 'eno minuto'; + case 'mm': + if (number === 1) { + result += withoutSuffix ? 'minuta' : 'minuto'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'minuti' : 'minutama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'minute' : 'minutami'; + } else { + result += withoutSuffix || isFuture ? 'minut' : 'minutami'; + } + return result; + case 'h': + return withoutSuffix ? 'ena ura' : 'eno uro'; + case 'hh': + if (number === 1) { + result += withoutSuffix ? 'ura' : 'uro'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'uri' : 'urama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'ure' : 'urami'; + } else { + result += withoutSuffix || isFuture ? 'ur' : 'urami'; + } + return result; + case 'd': + return withoutSuffix || isFuture ? 'en dan' : 'enim dnem'; + case 'dd': + if (number === 1) { + result += withoutSuffix || isFuture ? 'dan' : 'dnem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'dni' : 'dnevoma'; + } else { + result += withoutSuffix || isFuture ? 'dni' : 'dnevi'; + } + return result; + case 'M': + return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem'; + case 'MM': + if (number === 1) { + result += withoutSuffix || isFuture ? 'mesec' : 'mesecem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'meseca' : 'mesecema'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'mesece' : 'meseci'; + } else { + result += withoutSuffix || isFuture ? 'mesecev' : 'meseci'; + } + return result; + case 'y': + return withoutSuffix || isFuture ? 'eno leto' : 'enim letom'; + case 'yy': + if (number === 1) { + result += withoutSuffix || isFuture ? 'leto' : 'letom'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'leti' : 'letoma'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'leta' : 'leti'; + } else { + result += withoutSuffix || isFuture ? 'let' : 'leti'; + } + return result; + } + } + + var sl = moment.defineLocale('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', + LTS : 'LT:ss', + 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: + return '[prejšnjo] [nedeljo] [ob] LT'; + case 3: + return '[prejšnjo] [sredo] [ob] LT'; + case 6: + return '[prejšnjo] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prejšnji] dddd [ob] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'čez %s', + past : 'pred %s', + s : processRelativeTime, + m : processRelativeTime, + mm : processRelativeTime, + h : processRelativeTime, + hh : processRelativeTime, + d : processRelativeTime, + dd : processRelativeTime, + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return sl; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/sq.js b/bower_components/moment/locale/sq.js new file mode 100644 index 0000000..ce587cc --- /dev/null +++ b/bower_components/moment/locale/sq.js @@ -0,0 +1,68 @@ +//! moment.js locale configuration +//! locale : Albanian (sq) +//! author : Flakërim Ismani : https://github.com/flakerimi +//! author: Menelion Elensúle: https://github.com/Oire (tests) +//! author : Oerd Cukalla : https://github.com/oerd (fixes) + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var sq = moment.defineLocale('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 Martë_E Mërkurë_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('_'), + meridiemParse: /PD|MD/, + isPM: function (input) { + return input.charAt(0) === 'M'; + }, + meridiem : function (hours, minutes, isLower) { + return hours < 12 ? 'PD' : 'MD'; + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : '[Nesër në] LT', + nextWeek : 'dddd [në] LT', + lastDay : '[Dje në] LT', + lastWeek : 'dddd [e kaluar në] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'në %s', + past : '%s më parë', + s : 'disa sekonda', + m : 'një minutë', + mm : '%d minuta', + h : 'një orë', + hh : '%d orë', + d : 'një ditë', + dd : '%d ditë', + M : 'një muaj', + MM : '%d muaj', + y : 'një vit', + yy : '%d vite' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return sq; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/sr-cyrl.js b/bower_components/moment/locale/sr-cyrl.js new file mode 100644 index 0000000..8414596 --- /dev/null +++ b/bower_components/moment/locale/sr-cyrl.js @@ -0,0 +1,107 @@ +//! moment.js locale configuration +//! locale : Serbian-cyrillic (sr-cyrl) +//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var translator = { + words: { //Different grammatical cases + m: ['један минут', 'једне минуте'], + mm: ['минут', 'минуте', 'минута'], + h: ['један сат', 'једног сата'], + hh: ['сат', 'сата', 'сати'], + dd: ['дан', 'дана', 'дана'], + MM: ['месец', 'месеца', 'месеци'], + yy: ['година', 'године', 'година'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var sr_cyrl = moment.defineLocale('sr-cyrl', { + months: ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'], + monthsShort: ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'], + weekdays: ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'], + weekdaysShort: ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'], + weekdaysMin: ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'], + longDateFormat: { + LT: 'H:mm', + LTS : 'LT:ss', + 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: function () { + switch (this.day()) { + case 0: + return '[у] [недељу] [у] LT'; + case 3: + return '[у] [среду] [у] LT'; + case 6: + return '[у] [суботу] [у] LT'; + case 1: + case 2: + case 4: + case 5: + return '[у] dddd [у] LT'; + } + }, + lastDay : '[јуче у] LT', + lastWeek : function () { + var lastWeekDays = [ + '[прошле] [недеље] [у] LT', + '[прошлог] [понедељка] [у] LT', + '[прошлог] [уторка] [у] LT', + '[прошле] [среде] [у] LT', + '[прошлог] [четвртка] [у] LT', + '[прошлог] [петка] [у] LT', + '[прошле] [суботе] [у] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'за %s', + past : 'пре %s', + s : 'неколико секунди', + m : translator.translate, + mm : translator.translate, + h : translator.translate, + hh : translator.translate, + d : 'дан', + dd : translator.translate, + M : 'месец', + MM : translator.translate, + y : 'годину', + yy : translator.translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return sr_cyrl; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/sr.js b/bower_components/moment/locale/sr.js new file mode 100644 index 0000000..923b018 --- /dev/null +++ b/bower_components/moment/locale/sr.js @@ -0,0 +1,107 @@ +//! moment.js locale configuration +//! locale : Serbian-latin (sr) +//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jedne minute'], + mm: ['minut', 'minute', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mesec', 'meseca', 'meseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var sr = moment.defineLocale('sr', { + months: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'], + monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'], + weekdays: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'], + weekdaysShort: ['ned.', 'pon.', 'uto.', 'sre.', 'čet.', 'pet.', 'sub.'], + weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'], + longDateFormat: { + LT: 'H:mm', + LTS : 'LT:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY LT', + LLLL: 'dddd, D. MMMM YYYY LT' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sutra u] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedelju] [u] LT'; + case 3: + return '[u] [sredu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedelje] [u] LT', + '[prošlog] [ponedeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'pre %s', + s : 'nekoliko sekundi', + m : translator.translate, + mm : translator.translate, + h : translator.translate, + hh : translator.translate, + d : 'dan', + dd : translator.translate, + M : 'mesec', + MM : translator.translate, + y : 'godinu', + yy : translator.translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + return sr; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/sv.js b/bower_components/moment/locale/sv.js new file mode 100644 index 0000000..df2421a --- /dev/null +++ b/bower_components/moment/locale/sv.js @@ -0,0 +1,66 @@ +//! moment.js locale configuration +//! locale : swedish (sv) +//! author : Jens Alm : https://github.com/ulmus + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var sv = moment.defineLocale('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', + LTS : 'LT:ss', + 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: '[På] dddd LT', + lastWeek: '[I] dddd[s] 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' + }, + ordinalParse: /\d{1,2}(e|a)/, + 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. + } + }); + + return sv; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/ta.js b/bower_components/moment/locale/ta.js new file mode 100644 index 0000000..f0291c8 --- /dev/null +++ b/bower_components/moment/locale/ta.js @@ -0,0 +1,94 @@ +//! moment.js locale configuration +//! locale : tamil (ta) +//! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404 + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var ta = moment.defineLocale('ta', { + months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'), + weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'), + weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 ஆண்டுகள்' + }, + ordinalParse: /\d{1,2}வது/, + ordinal : function (number) { + return number + 'வது'; + }, + // refer http://ta.wikipedia.org/s/1er1 + meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/, + meridiem : function (hour, minute, isLower) { + if (hour < 2) { + return ' யாமம்'; + } else if (hour < 6) { + return ' வைகறை'; // வைகறை + } else if (hour < 10) { + return ' காலை'; // காலை + } else if (hour < 14) { + return ' நண்பகல்'; // நண்பகல் + } else if (hour < 18) { + return ' எற்பாடு'; // எற்பாடு + } else if (hour < 22) { + return ' மாலை'; // மாலை + } else { + return ' யாமம்'; + } + }, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'யாமம்') { + return hour < 2 ? hour : hour + 12; + } else if (meridiem === 'வைகறை' || meridiem === 'காலை') { + return hour; + } else if (meridiem === 'நண்பகல்') { + return hour >= 10 ? hour : hour + 12; + } else { + return hour + 12; + } + }, + 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. + } + }); + + return ta; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/th.js b/bower_components/moment/locale/th.js new file mode 100644 index 0000000..6fe2f44 --- /dev/null +++ b/bower_components/moment/locale/th.js @@ -0,0 +1,64 @@ +//! moment.js locale configuration +//! locale : thai (th) +//! author : Kridsada Thanabulpong : https://github.com/sirn + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var th = moment.defineLocale('th', { + months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'), + monthsShort : 'มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา'.split('_'), + weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'), + weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference + weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'), + longDateFormat : { + LT : 'H นาฬิกา m นาที', + LTS : 'LT s วินาที', + L : 'YYYY/MM/DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY เวลา LT', + LLLL : 'วันddddที่ D MMMM YYYY เวลา LT' + }, + meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/, + isPM: function (input) { + return input === 'หลังเที่ยง'; + }, + 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 ปี' + } + }); + + return th; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/tl-ph.js b/bower_components/moment/locale/tl-ph.js new file mode 100644 index 0000000..938fd9d --- /dev/null +++ b/bower_components/moment/locale/tl-ph.js @@ -0,0 +1,61 @@ +//! moment.js locale configuration +//! locale : Tagalog/Filipino (tl-ph) +//! author : Dan Hagman + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var tl_ph = moment.defineLocale('tl-ph', { + months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'), + monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'), + weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'), + weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'), + weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'MM/D/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY LT', + LLLL : 'dddd, MMMM DD, YYYY LT' + }, + calendar : { + sameDay: '[Ngayon sa] LT', + nextDay: '[Bukas sa] LT', + nextWeek: 'dddd [sa] LT', + lastDay: '[Kahapon sa] LT', + lastWeek: 'dddd [huling linggo] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'sa loob ng %s', + past : '%s ang nakalipas', + s : 'ilang segundo', + m : 'isang minuto', + mm : '%d minuto', + h : 'isang oras', + hh : '%d oras', + d : 'isang araw', + dd : '%d araw', + M : 'isang buwan', + MM : '%d buwan', + y : 'isang taon', + yy : '%d taon' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + 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. + } + }); + + return tl_ph; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/tr.js b/bower_components/moment/locale/tr.js new file mode 100644 index 0000000..f92e81d --- /dev/null +++ b/bower_components/moment/locale/tr.js @@ -0,0 +1,89 @@ +//! moment.js locale configuration +//! locale : turkish (tr) +//! authors : Erhan Gundogan : https://github.com/erhangundogan, +//! Burak Yiğit Kaya: https://github.com/BYK + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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 tr = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/, + 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. + } + }); + + return tr; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/tzm-latn.js b/bower_components/moment/locale/tzm-latn.js new file mode 100644 index 0000000..0442d13 --- /dev/null +++ b/bower_components/moment/locale/tzm-latn.js @@ -0,0 +1,57 @@ +//! moment.js locale configuration +//! locale : Morocco Central Atlas Tamaziɣt in Latin (tzm-latn) +//! author : Abdel Said : https://github.com/abdelsaid + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var tzm_latn = moment.defineLocale('tzm-latn', { + 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', + LTS : 'LT:ss', + 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. + } + }); + + return tzm_latn; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/tzm.js b/bower_components/moment/locale/tzm.js new file mode 100644 index 0000000..a64d910 --- /dev/null +++ b/bower_components/moment/locale/tzm.js @@ -0,0 +1,57 @@ +//! moment.js locale configuration +//! locale : Morocco Central Atlas Tamaziɣt (tzm) +//! author : Abdel Said : https://github.com/abdelsaid + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var tzm = moment.defineLocale('tzm', { + months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS: 'LT:ss', + 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. + } + }); + + return tzm; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/uk.js b/bower_components/moment/locale/uk.js new file mode 100644 index 0000000..3a85ef8 --- /dev/null +++ b/bower_components/moment/locale/uk.js @@ -0,0 +1,152 @@ +//! moment.js locale configuration +//! locale : ukrainian (uk) +//! author : zemlanin : https://github.com/zemlanin +//! Author : Menelion Elensúle : https://github.com/Oire + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + 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'; + }; + } + + var uk = moment.defineLocale('uk', { + months : monthsCaseReplace, + monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'), + weekdays : weekdaysCaseReplace, + weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 + }, + // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason + meridiemParse: /ночі|ранку|дня|вечора/, + isPM: function (input) { + return /^(дня|вечора)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночі'; + } else if (hour < 12) { + return 'ранку'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечора'; + } + }, + ordinalParse: /\d{1,2}-(й|го)/, + 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. + } + }); + + return uk; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/uz.js b/bower_components/moment/locale/uz.js new file mode 100644 index 0000000..4a84d00 --- /dev/null +++ b/bower_components/moment/locale/uz.js @@ -0,0 +1,57 @@ +//! moment.js locale configuration +//! locale : uzbek (uz) +//! author : Sardor Muminov : https://github.com/muminoff + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var uz = moment.defineLocale('uz', { + months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'), + weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'), + weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'), + weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'D MMMM YYYY, dddd 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 : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 4th is the first week of the year. + } + }); + + return uz; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/vi.js b/bower_components/moment/locale/vi.js new file mode 100644 index 0000000..4b6d289 --- /dev/null +++ b/bower_components/moment/locale/vi.js @@ -0,0 +1,65 @@ +//! moment.js locale configuration +//! locale : vietnamese (vi) +//! author : Bang Nguyen : https://github.com/bangnk + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var vi = moment.defineLocale('vi', { + months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'), + monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'), + weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'), + weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM [năm] YYYY', + LLL : 'D MMMM [năm] YYYY LT', + LLLL : 'dddd, D MMMM [năm] YYYY LT', + l : 'DD/M/YYYY', + ll : 'D MMM YYYY', + lll : 'D MMM YYYY LT', + llll : 'ddd, D MMM YYYY LT' + }, + calendar : { + sameDay: '[Hôm nay lúc] LT', + nextDay: '[Ngày mai lúc] LT', + nextWeek: 'dddd [tuần tới lúc] LT', + lastDay: '[Hôm qua lúc] LT', + lastWeek: 'dddd [tuần rồi lúc] LT', + sameElse: 'L' + }, + relativeTime : { + future : '%s tới', + past : '%s trước', + s : 'vài giây', + m : 'một phút', + mm : '%d phút', + h : 'một giờ', + hh : '%d giờ', + d : 'một ngày', + dd : '%d ngày', + M : 'một tháng', + MM : '%d tháng', + y : 'một năm', + yy : '%d năm' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + 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. + } + }); + + return vi; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/zh-cn.js b/bower_components/moment/locale/zh-cn.js new file mode 100644 index 0000000..056c5ad --- /dev/null +++ b/bower_components/moment/locale/zh-cn.js @@ -0,0 +1,126 @@ +//! moment.js locale configuration +//! locale : chinese (zh-cn) +//! author : suupic : https://github.com/suupic +//! author : Zeno Zeng : https://github.com/zenozeng + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var zh_cn = moment.defineLocale('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分', + LTS : 'Ah点m分s秒', + L : 'YYYY-MM-DD', + LL : 'YYYY年MMMD日', + LLL : 'YYYY年MMMD日LT', + LLLL : 'YYYY年MMMD日ddddLT', + l : 'YYYY-MM-DD', + ll : 'YYYY年MMMD日', + lll : 'YYYY年MMMD日LT', + llll : 'YYYY年MMMD日ddddLT' + }, + meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '凌晨' || meridiem === '早上' || + meridiem === '上午') { + return hour; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } else { + // '中午' + return hour >= 11 ? hour : hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 600) { + return '凌晨'; + } else if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : function () { + return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT'; + }, + nextDay : function () { + return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT'; + }, + lastDay : function () { + return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT'; + }, + nextWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment().startOf('week'); + prefix = this.unix() - startOfWeek.unix() >= 7 * 24 * 3600 ? '[下]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + lastWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment().startOf('week'); + prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + sameElse : 'LL' + }, + ordinalParse: /\d{1,2}(日|月|周)/, + 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 年' + }, + week : { + // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 + 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. + } + }); + + return zh_cn; + +}));
\ No newline at end of file diff --git a/bower_components/moment/locale/zh-tw.js b/bower_components/moment/locale/zh-tw.js new file mode 100644 index 0000000..ce20225 --- /dev/null +++ b/bower_components/moment/locale/zh-tw.js @@ -0,0 +1,100 @@ +//! moment.js locale configuration +//! locale : traditional chinese (zh-tw) +//! author : Ben : https://github.com/ben-lin + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + + var zh_tw = moment.defineLocale('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分', + LTS : 'Ah點m分s秒', + 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' + }, + meridiemParse: /早上|上午|中午|下午|晚上/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '早上' || meridiem === '上午') { + return hour; + } else if (meridiem === '中午') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + ordinalParse: /\d{1,2}(日|月|週)/, + 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年' + } + }); + + return zh_tw; + +}));
\ No newline at end of file diff --git a/bower_components/moment/min/locales.js b/bower_components/moment/min/locales.js new file mode 100644 index 0000000..4dfa44c --- /dev/null +++ b/bower_components/moment/min/locales.js @@ -0,0 +1,6632 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + //! moment.js locale configuration + //! locale : afrikaans (af) + //! author : Werner Mollentze : https://github.com/wernerm + + var af = moment.defineLocale('af', { + months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'), + weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'), + weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'), + meridiemParse: /vm|nm/i, + isPM : function (input) { + return /^nm$/i.test(input); + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower ? 'vm' : 'VM'; + } else { + return isLower ? 'nm' : 'NM'; + } + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd, D MMMM YYYY LT' + }, + calendar : { + sameDay : '[Vandag om] LT', + nextDay : '[Môre om] LT', + nextWeek : 'dddd [om] LT', + lastDay : '[Gister om] LT', + lastWeek : '[Laas] dddd [om] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'oor %s', + past : '%s gelede', + s : '\'n paar sekondes', + m : '\'n minuut', + mm : '%d minute', + h : '\'n uur', + hh : '%d ure', + d : '\'n dag', + dd : '%d dae', + M : '\'n maand', + MM : '%d maande', + y : '\'n jaar', + yy : '%d jaar' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter + }, + week : { + dow : 1, // Maandag is die eerste dag van die week. + doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar. + } + }); + + //! moment.js locale configuration + //! locale : Moroccan Arabic (ar-ma) + //! author : ElFadili Yassine : https://github.com/ElFadiliY + //! author : Abdel Said : https://github.com/abdelsaid + + var ar_ma = moment.defineLocale('ar-ma', { + months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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. + } + }); + + //! moment.js locale configuration + //! locale : Arabic Saudi Arabia (ar-sa) + //! author : Suhail Alkowaileet : https://github.com/xsoh + + var ar_sa__symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' + }, ar_sa__numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' + }; + + var ar_sa = moment.defineLocale('ar-sa', { + months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D MMMM YYYY LT' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + 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 ar_sa__numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ar_sa__symbolMap[match]; + }).replace(/,/g, '،'); + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Tunisian Arabic (ar-tn) + + var ar_tn = moment.defineLocale('ar-tn', { + months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat: { + LT: 'HH:mm', + LTS: 'LT:ss', + 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: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! Locale: Arabic (ar) + //! Author: Abdel Said: https://github.com/abdelsaid + //! Changes in months, weekdays: Ahmed Elkhatib + //! Native plural forms: forabi https://github.com/forabi + + var ar__symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' + }, ar__numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' + }, pluralForm = function (n) { + return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5; + }, plurals = { + s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'], + m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'], + h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'], + d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'], + M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'], + y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام'] + }, pluralize = function (u) { + return function (number, withoutSuffix, string, isFuture) { + var f = pluralForm(number), + str = plurals[u][pluralForm(number)]; + if (f === 2) { + str = str[withoutSuffix ? 0 : 1]; + } + return str.replace(/%d/i, number); + }; + }, ar__months = [ + 'كانون الثاني يناير', + 'شباط فبراير', + 'آذار مارس', + 'نيسان أبريل', + 'أيار مايو', + 'حزيران يونيو', + 'تموز يوليو', + 'آب أغسطس', + 'أيلول سبتمبر', + 'تشرين الأول أكتوبر', + 'تشرين الثاني نوفمبر', + 'كانون الأول ديسمبر' + ]; + + var ar = moment.defineLocale('ar', { + months : ar__months, + monthsShort : ar__months, + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'D/\u200FM/\u200FYYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D MMMM YYYY LT' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + 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 : pluralize('s'), + m : pluralize('m'), + mm : pluralize('m'), + h : pluralize('h'), + hh : pluralize('h'), + d : pluralize('d'), + dd : pluralize('d'), + M : pluralize('M'), + MM : pluralize('M'), + y : pluralize('y'), + yy : pluralize('y') + }, + preparse: function (string) { + return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { + return ar__numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ar__symbolMap[match]; + }).replace(/,/g, '،'); + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : azerbaijani (az) + //! author : topchiyev : https://github.com/topchiyev + + var az__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 az = moment.defineLocale('az', { + months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'), + monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'), + weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'), + weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'), + weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : '[sabah saat] LT', + nextWeek : '[gələn həftə] dddd [saat] LT', + lastDay : '[dünən] LT', + lastWeek : '[keçən həftə] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s sonra', + past : '%s əvvəl', + s : 'birneçə saniyyə', + m : 'bir dəqiqə', + mm : '%d dəqiqə', + h : 'bir saat', + hh : '%d saat', + d : 'bir gün', + dd : '%d gün', + M : 'bir ay', + MM : '%d ay', + y : 'bir il', + yy : '%d il' + }, + meridiemParse: /gecə|səhər|gündüz|axşam/, + isPM : function (input) { + return /^(gündüz|axşam)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'gecə'; + } else if (hour < 12) { + return 'səhər'; + } else if (hour < 17) { + return 'gündüz'; + } else { + return 'axşam'; + } + }, + ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/, + 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 + (az__suffixes[a] || az__suffixes[b] || az__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. + } + }); + + //! moment.js locale configuration + //! locale : belarusian (be) + //! author : Dmitry Demidov : https://github.com/demidov91 + //! author: Praleska: http://praleska.pro/ + //! Author : Menelion Elensúle : https://github.com/Oire + + function be__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 be__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін', + 'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін', + 'dd': 'дзень_дні_дзён', + 'MM': 'месяц_месяцы_месяцаў', + 'yy': 'год_гады_гадоў' + }; + if (key === 'm') { + return withoutSuffix ? 'хвіліна' : 'хвіліну'; + } + else if (key === 'h') { + return withoutSuffix ? 'гадзіна' : 'гадзіну'; + } + else { + return number + ' ' + be__plural(format[key], +number); + } + } + function be__monthsCaseReplace(m, format) { + var months = { + 'nominative': 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_'), + 'accusative': 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_') + }, + nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; + } + function be__weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'), + 'accusative': 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_') + }, + nounCase = (/\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/).test(format) ? + 'accusative' : + 'nominative'; + return weekdays[nounCase][m.day()]; + } + + var be = moment.defineLocale('be', { + months : be__monthsCaseReplace, + monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'), + weekdays : be__weekdaysCaseReplace, + weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 '[У] dddd [ў] LT'; + }, + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return '[У мінулую] dddd [ў] LT'; + case 1: + case 2: + case 4: + return '[У мінулы] dddd [ў] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'праз %s', + past : '%s таму', + s : 'некалькі секунд', + m : be__relativeTimeWithPlural, + mm : be__relativeTimeWithPlural, + h : be__relativeTimeWithPlural, + hh : be__relativeTimeWithPlural, + d : 'дзень', + dd : be__relativeTimeWithPlural, + M : 'месяц', + MM : be__relativeTimeWithPlural, + y : 'год', + yy : be__relativeTimeWithPlural + }, + meridiemParse: /ночы|раніцы|дня|вечара/, + isPM : function (input) { + return /^(дня|вечара)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночы'; + } else if (hour < 12) { + return 'раніцы'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечара'; + } + }, + ordinalParse: /\d{1,2}-(і|ы|га)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : 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. + } + }); + + //! moment.js locale configuration + //! locale : bulgarian (bg) + //! author : Krasen Borisov : https://github.com/kraz + + var bg = moment.defineLocale('bg', { + months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'), + weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + 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 години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Bengali (bn) + //! author : Kaushik Gandhi : https://github.com/kaushikgandhi + + var bn__symbolMap = { + '1': '১', + '2': '২', + '3': '৩', + '4': '৪', + '5': '৫', + '6': '৬', + '7': '৭', + '8': '৮', + '9': '৯', + '0': '০' + }, + bn__numberMap = { + '১': '1', + '২': '2', + '৩': '3', + '৪': '4', + '৫': '5', + '৬': '6', + '৭': '7', + '৮': '8', + '৯': '9', + '০': '0' + }; + + var bn = moment.defineLocale('bn', { + months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'), + monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split('_'), + weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রুবার_শনিবার'.split('_'), + weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্রু_শনি'.split('_'), + weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'), + longDateFormat : { + LT : 'A h:mm সময়', + LTS : 'A h:mm:ss সময়', + 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 bn__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return bn__symbolMap[match]; + }); + }, + meridiemParse: /রাত|শকাল|দুপুর|বিকেল|রাত/, + isPM: function (input) { + return /^(দুপুর|বিকেল|রাত)$/.test(input); + }, + //Bengali is a vast language its spoken + //in different forms in various parts of the world. + //I have just generalized with most common one used + 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. + } + }); + + //! moment.js locale configuration + //! locale : tibetan (bo) + //! author : Thupten N. Chakrishar : https://github.com/vajradog + + var bo__symbolMap = { + '1': '༡', + '2': '༢', + '3': '༣', + '4': '༤', + '5': '༥', + '6': '༦', + '7': '༧', + '8': '༨', + '9': '༩', + '0': '༠' + }, + bo__numberMap = { + '༡': '1', + '༢': '2', + '༣': '3', + '༤': '4', + '༥': '5', + '༦': '6', + '༧': '7', + '༨': '8', + '༩': '9', + '༠': '0' + }; + + var bo = moment.defineLocale('bo', { + months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'), + weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + longDateFormat : { + LT : 'A h:mm', + LTS : 'LT:ss', + 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 : '[བདུན་ཕྲག་རྗེས་མ], 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 bo__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return bo__symbolMap[match]; + }); + }, + meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/, + isPM: function (input) { + return /^(ཉིན་གུང|དགོང་དག|མཚན་མོ)$/.test(input); + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : 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); + } + + var br = moment.defineLocale('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', + LTS : 'h[e]mm:ss 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 + }, + ordinalParse: /\d{1,2}(añ|vet)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : bosnian (bs) + //! author : Nedim Cholich : https://github.com/frontyard + //! based on (hr) translation by Bojan Marković + + function bs__translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } + } + + var bs = moment.defineLocale('bs', { + months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'), + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : bs__translate, + mm : bs__translate, + h : bs__translate, + hh : bs__translate, + d : 'dan', + dd : bs__translate, + M : 'mjesec', + MM : bs__translate, + y : 'godinu', + yy : bs__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : catalan (ca) + //! author : Juan G. Hurtado : https://github.com/juanghurtado + + var ca = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(r|n|t|è|a)/, + ordinal : function (number, period) { + var output = (number === 1) ? 'r' : + (number === 2) ? 'n' : + (number === 3) ? 'r' : + (number === 4) ? 't' : 'è'; + if (period === 'w' || period === 'W') { + output = 'a'; + } + 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. + } + }); + + //! moment.js locale configuration + //! locale : czech (cs) + //! author : petrbela : https://github.com/petrbela + + var cs__months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'), + cs__monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_'); + function cs__plural(n) { + return (n > 1) && (n < 5) && (~~(n / 10) !== 1); + } + function cs__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 sekund' : 'pár sekundami'; + 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 + (cs__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 + (cs__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 + (cs__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 + (cs__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 + (cs__plural(number) ? 'roky' : 'let'); + } else { + return result + 'lety'; + } + break; + } + } + + var cs = moment.defineLocale('cs', { + months : cs__months, + monthsShort : cs__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; + }(cs__months, cs__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', + LTS : 'LT:ss', + 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 : cs__translate, + m : cs__translate, + mm : cs__translate, + h : cs__translate, + hh : cs__translate, + d : cs__translate, + dd : cs__translate, + M : cs__translate, + MM : cs__translate, + y : cs__translate, + yy : cs__translate + }, + ordinalParse : /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : chuvash (cv) + //! author : Anatoly Mironov : https://github.com/mirontoli + + var cv = moment.defineLocale('cv', { + months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'), + monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'), + weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'), + weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'), + weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 ҫул' + }, + ordinalParse: /\d{1,2}-мӗш/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Welsh (cy) + //! author : Robert Allen + + var cy = moment.defineLocale('cy', { + months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'), + monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'), + weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'), + weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'), + weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'), + // time formats are the same as en-gb + longDateFormat: { + LT: 'HH:mm', + LTS : 'LT:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY LT', + LLLL: 'dddd, D MMMM YYYY LT' + }, + calendar: { + sameDay: '[Heddiw am] LT', + nextDay: '[Yfory am] LT', + nextWeek: 'dddd [am] LT', + lastDay: '[Ddoe am] LT', + lastWeek: 'dddd [diwethaf am] LT', + sameElse: 'L' + }, + relativeTime: { + future: 'mewn %s', + past: '%s yn ôl', + s: 'ychydig eiliadau', + m: 'munud', + mm: '%d munud', + h: 'awr', + hh: '%d awr', + d: 'diwrnod', + dd: '%d diwrnod', + M: 'mis', + MM: '%d mis', + y: 'blwyddyn', + yy: '%d flynedd' + }, + ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/, + // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh + ordinal: function (number) { + var b = number, + output = '', + lookup = [ + '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed + 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed + ]; + if (b > 20) { + if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) { + output = 'fed'; // not 30ain, 70ain or 90ain + } else { + output = 'ain'; + } + } else if (b > 0) { + output = lookup[b]; + } + 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. + } + }); + + //! moment.js locale configuration + //! locale : danish (da) + //! author : Ulrik Nielsen : https://github.com/mrbase + + var da = moment.defineLocale('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', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd [d.] 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' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : austrian german (de-at) + //! author : lluchs : https://github.com/lluchs + //! author: Menelion Elensúle: https://github.com/Oire + //! author : Martin Groller : https://github.com/MadMG + + function de_at__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]; + } + + var de_at = moment.defineLocale('de-at', { + months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort : 'Jän._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: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay: '[Heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[Morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[Gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + relativeTime : { + future : 'in %s', + past : 'vor %s', + s : 'ein paar Sekunden', + m : de_at__processRelativeTime, + mm : '%d Minuten', + h : de_at__processRelativeTime, + hh : '%d Stunden', + d : de_at__processRelativeTime, + dd : de_at__processRelativeTime, + M : de_at__processRelativeTime, + MM : de_at__processRelativeTime, + y : de_at__processRelativeTime, + yy : de_at__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : german (de) + //! author : lluchs : https://github.com/lluchs + //! author: Menelion Elensúle: https://github.com/Oire + + function de__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]; + } + + var de = moment.defineLocale('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: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay: '[Heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[Morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[Gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + relativeTime : { + future : 'in %s', + past : 'vor %s', + s : 'ein paar Sekunden', + m : de__processRelativeTime, + mm : '%d Minuten', + h : de__processRelativeTime, + hh : '%d Stunden', + d : de__processRelativeTime, + dd : de__processRelativeTime, + M : de__processRelativeTime, + MM : de__processRelativeTime, + y : de__processRelativeTime, + yy : de__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : modern greek (el) + //! author : Aggelos Karalias : https://github.com/mehiel + + var el = moment.defineLocale('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 ? 'πμ' : 'ΠΜ'; + } + }, + isPM : function (input) { + return ((input + '').toLowerCase()[0] === 'μ'); + }, + meridiemParse : /[ΠΜ]\.?Μ?\.?/i, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss 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 : function () { + switch (this.day()) { + case 6: + return '[το προηγούμενο] dddd [{}] LT'; + default: + return '[την προηγούμενη] dddd [{}] LT'; + } + }, + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendarEl[key], + hours = mom && mom.hours(); + if (typeof output === 'function') { + output = output.apply(mom); + } + 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 χρόνια' + }, + ordinalParse: /\d{1,2}η/, + ordinal: '%dη', + 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. + } + }); + + //! moment.js locale configuration + //! locale : australian english (en-au) + + var en_au = moment.defineLocale('en-au', { + 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', + LTS : 'h:mm:ss 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' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : canadian english (en-ca) + //! author : Jonathan Abourbih : https://github.com/jonbca + + var en_ca = moment.defineLocale('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', + LTS : 'h:mm:ss 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' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + 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; + } + }); + + //! moment.js locale configuration + //! locale : great britain english (en-gb) + //! author : Chris Gedrim : https://github.com/chrisgedrim + + var en_gb = moment.defineLocale('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', + LTS : 'HH:mm:ss', + 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' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : 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! + + var eo = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + meridiemParse: /[ap]\.t\.m/i, + isPM: function (input) { + return input.charAt(0).toLowerCase() === 'p'; + }, + 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' + }, + ordinalParse: /\d{1,2}a/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : spanish (es) + //! author : Julio Napurí : https://github.com/julionc + + var monthsShortDot = 'Ene._Feb._Mar._Abr._May._Jun._Jul._Ago._Sep._Oct._Nov._Dic.'.split('_'), + es__monthsShort = 'Ene_Feb_Mar_Abr_May_Jun_Jul_Ago_Sep_Oct_Nov_Dic'.split('_'); + + var es = moment.defineLocale('es', { + months : 'Enero_Febrero_Marzo_Abril_Mayo_Junio_Julio_Agosto_Septiembre_Octubre_Noviembre_Diciembre'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return es__monthsShort[m.month()]; + } else { + return monthsShortDot[m.month()]; + } + }, + 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', + LTS : 'LT:ss', + 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' + }, + ordinalParse : /\d{1,2}º/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : estonian (et) + //! author : Henry Kehlmann : https://github.com/madhenry + //! improvements : Illimar Tambek : https://github.com/ragulka + + function et__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'], + 'm' : ['ühe minuti', 'üks minut'], + 'mm': [number + ' minuti', number + ' minutit'], + 'h' : ['ühe tunni', 'tund aega', 'üks tund'], + 'hh': [number + ' tunni', number + ' tundi'], + 'd' : ['ühe päeva', 'üks päev'], + 'M' : ['kuu aja', 'kuu aega', 'üks kuu'], + 'MM': [number + ' kuu', number + ' kuud'], + 'y' : ['ühe aasta', 'aasta', 'üks aasta'], + 'yy': [number + ' aasta', number + ' aastat'] + }; + if (withoutSuffix) { + return format[key][2] ? format[key][2] : format[key][1]; + } + return isFuture ? format[key][0] : format[key][1]; + } + + var et = moment.defineLocale('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', + LTS : 'LT:ss', + 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 : et__processRelativeTime, + m : et__processRelativeTime, + mm : et__processRelativeTime, + h : et__processRelativeTime, + hh : et__processRelativeTime, + d : et__processRelativeTime, + dd : '%d päeva', + M : et__processRelativeTime, + MM : et__processRelativeTime, + y : et__processRelativeTime, + yy : et__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : euskara (eu) + //! author : Eneko Illarramendi : https://github.com/eillarra + + var eu = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Persian (fa) + //! author : Ebrahim Byagowi : https://github.com/ebraminio + + var fa__symbolMap = { + '1': '۱', + '2': '۲', + '3': '۳', + '4': '۴', + '5': '۵', + '6': '۶', + '7': '۷', + '8': '۸', + '9': '۹', + '0': '۰' + }, fa__numberMap = { + '۱': '1', + '۲': '2', + '۳': '3', + '۴': '4', + '۵': '5', + '۶': '6', + '۷': '7', + '۸': '8', + '۹': '9', + '۰': '0' + }; + + var fa = moment.defineLocale('fa', { + months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd, D MMMM YYYY LT' + }, + meridiemParse: /قبل از ظهر|بعد از ظهر/, + isPM: function (input) { + return /بعد از ظهر/.test(input); + }, + 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 fa__numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return fa__symbolMap[match]; + }).replace(/,/g, '،'); + }, + ordinalParse: /\d{1,2}م/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : finnish (fi) + //! author : Tarmo Aidantausta : https://github.com/bleadof + + var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '), + numbersFuture = [ + 'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden', + numbersPast[7], numbersPast[8], numbersPast[9] + ]; + function fi__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 = verbalNumber(number, isFuture) + ' ' + result; + return result; + } + function verbalNumber(number, isFuture) { + return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number; + } + + var fi = moment.defineLocale('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', + LTS : 'HH.mm.ss', + 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 : fi__translate, + m : fi__translate, + mm : fi__translate, + h : fi__translate, + hh : fi__translate, + d : fi__translate, + dd : fi__translate, + M : fi__translate, + MM : fi__translate, + y : fi__translate, + yy : fi__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : faroese (fo) + //! author : Ragnar Johannesen : https://github.com/ragnar123 + + var fo = moment.defineLocale('fo', { + months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), + weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'), + weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'), + weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D. MMMM, YYYY LT' + }, + calendar : { + sameDay : '[Í dag kl.] LT', + nextDay : '[Í morgin kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[Í gjár kl.] LT', + lastWeek : '[síðstu] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'um %s', + past : '%s síðani', + s : 'fá sekund', + m : 'ein minutt', + mm : '%d minuttir', + h : 'ein tími', + hh : '%d tímar', + d : 'ein dagur', + dd : '%d dagar', + M : 'ein mánaði', + MM : '%d mánaðir', + y : 'eitt ár', + yy : '%d ár' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : canadian french (fr-ca) + //! author : Jonathan Abourbih : https://github.com/jonbca + + var fr_ca = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(er|)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : ''); + } + }); + + //! moment.js locale configuration + //! locale : french (fr) + //! author : John Fischer : https://github.com/jfroffice + + var fr = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(er|)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : frisian (fy) + //! author : Robin van der Vliet : https://github.com/robin0van0der0v + + var fy__monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_'), + fy__monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'); + + var fy = moment.defineLocale('fy', { + months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return fy__monthsShortWithoutDots[m.month()]; + } else { + return fy__monthsShortWithDots[m.month()]; + } + }, + weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'), + weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'), + weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D MMMM YYYY LT' + }, + calendar : { + sameDay: '[hjoed om] LT', + nextDay: '[moarn om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[juster om] LT', + lastWeek: '[ôfrûne] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'oer %s', + past : '%s lyn', + s : 'in pear sekonden', + m : 'ien minút', + mm : '%d minuten', + h : 'ien oere', + hh : '%d oeren', + d : 'ien dei', + dd : '%d dagen', + M : 'ien moanne', + MM : '%d moannen', + y : 'ien jier', + yy : '%d jierren' + }, + ordinalParse: /\d{1,2}(ste|de)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : galician (gl) + //! author : Juan G. Hurtado : https://github.com/juanghurtado + + var gl = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse : /\d{1,2}º/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Hebrew (he) + //! author : Tomer Cohen : https://github.com/tomer + //! author : Moshe Simantov : https://github.com/DevelopmentIL + //! author : Tal Ater : https://github.com/TalAter + + var he = moment.defineLocale('he', { + months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'), + monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'), + weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'), + weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'), + weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : function (number) { + if (number === 2) { + return 'שעתיים'; + } + return number + ' שעות'; + }, + d : 'יום', + dd : function (number) { + if (number === 2) { + return 'יומיים'; + } + return number + ' ימים'; + }, + M : 'חודש', + MM : function (number) { + if (number === 2) { + return 'חודשיים'; + } + return number + ' חודשים'; + }, + y : 'שנה', + yy : function (number) { + if (number === 2) { + return 'שנתיים'; + } else if (number % 10 === 0 && number !== 10) { + return number + ' שנה'; + } + return number + ' שנים'; + } + } + }); + + //! moment.js locale configuration + //! locale : hindi (hi) + //! author : Mayank Singhal : https://github.com/mayanksinghal + + var hi__symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + hi__numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var hi = moment.defineLocale('hi', { + months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'), + monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'), + weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm बजे', + LTS : 'A h:mm:ss बजे', + 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 hi__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return hi__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. + meridiemParse: /रात|सुबह|दोपहर|शाम/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सुबह') { + return hour; + } else if (meridiem === 'दोपहर') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'शाम') { + return hour + 12; + } + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : hrvatski (hr) + //! author : Bojan Marković : https://github.com/bmarkovic + + function hr__translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } + } + + var hr = moment.defineLocale('hr', { + months : 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_'), + monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'), + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : hr__translate, + mm : hr__translate, + h : hr__translate, + hh : hr__translate, + d : 'dan', + dd : hr__translate, + M : 'mjesec', + MM : hr__translate, + y : 'godinu', + yy : hr__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : 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 hu__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]'; + } + + var hu = moment.defineLocale('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 : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'), + weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + L : 'YYYY.MM.DD.', + LL : 'YYYY. MMMM D.', + LLL : 'YYYY. MMMM D., LT', + LLLL : 'YYYY. MMMM D., dddd LT' + }, + meridiemParse: /de|du/i, + isPM: function (input) { + return input.charAt(1).toLowerCase() === 'u'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower === true ? 'de' : 'DE'; + } else { + return isLower === true ? 'du' : 'DU'; + } + }, + 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 : hu__translate, + m : hu__translate, + mm : hu__translate, + h : hu__translate, + hh : hu__translate, + d : hu__translate, + dd : hu__translate, + M : hu__translate, + MM : hu__translate, + y : hu__translate, + yy : hu__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Armenian (hy-am) + //! author : Armendarabyan : https://github.com/armendarabyan + + function hy_am__monthsCaseReplace(m, format) { + var months = { + 'nominative': 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_'), + 'accusative': 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_') + }, + nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; + } + function hy_am__monthsShortCaseReplace(m, format) { + var monthsShort = 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'); + return monthsShort[m.month()]; + } + function hy_am__weekdaysCaseReplace(m, format) { + var weekdays = 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'); + return weekdays[m.day()]; + } + + var hy_am = moment.defineLocale('hy-am', { + months : hy_am__monthsCaseReplace, + monthsShort : hy_am__monthsShortCaseReplace, + weekdays : hy_am__weekdaysCaseReplace, + weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 'dddd [օրը ժամը] LT'; + }, + lastWeek: function () { + 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 տարի' + }, + meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/, + isPM: function (input) { + return /^(ցերեկվա|երեկոյան)$/.test(input); + }, + meridiem : function (hour) { + if (hour < 4) { + return 'գիշերվա'; + } else if (hour < 12) { + return 'առավոտվա'; + } else if (hour < 17) { + return 'ցերեկվա'; + } else { + return 'երեկոյան'; + } + }, + ordinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/, + ordinal: function (number, period) { + switch (period) { + case 'DDD': + case 'w': + case 'W': + case 'DDDo': + if (number === 1) { + return number + '-ին'; + } + 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. + } + }); + + //! moment.js locale configuration + //! locale : Bahasa Indonesia (id) + //! author : Mohammad Satrio Utomo : https://github.com/tyok + //! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan + + var id = moment.defineLocale('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', + LTS : 'LT.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] LT', + LLLL : 'dddd, D MMMM YYYY [pukul] LT' + }, + meridiemParse: /pagi|siang|sore|malam/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'siang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sore' || meridiem === 'malam') { + return hour + 12; + } + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : icelandic (is) + //! author : Hinrik Örn Sigurðsson : https://github.com/hinrik + + function is__plural(n) { + if (n % 100 === 11) { + return true; + } else if (n % 10 === 1) { + return false; + } + return true; + } + function is__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 (is__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 (is__plural(number)) { + return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum'); + } + return result + 'klukkustund'; + case 'd': + if (withoutSuffix) { + return 'dagur'; + } + return isFuture ? 'dag' : 'degi'; + case 'dd': + if (is__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 (is__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 (is__plural(number)) { + return result + (withoutSuffix || isFuture ? 'ár' : 'árum'); + } + return result + (withoutSuffix || isFuture ? 'ár' : 'ári'); + } + } + + var is = moment.defineLocale('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', + LTS : 'LT:ss', + 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 : is__translate, + m : is__translate, + mm : is__translate, + h : 'klukkustund', + hh : is__translate, + d : is__translate, + dd : is__translate, + M : is__translate, + MM : is__translate, + y : is__translate, + yy : is__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : italian (it) + //! author : Lorenzo : https://github.com/aliem + //! author: Mattia Larentis: https://github.com/nostalgiaz + + var it = moment.defineLocale('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', + LTS : 'LT:ss', + 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: function () { + switch (this.day()) { + case 0: + return '[la scorsa] dddd [alle] LT'; + default: + return '[lo scorso] dddd [alle] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : function (s) { + return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s; + }, + past : '%s fa', + s : 'alcuni 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' + }, + ordinalParse : /\d{1,2}º/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : japanese (ja) + //! author : LI Long : https://github.com/baryon + + var ja = moment.defineLocale('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分', + LTS : 'LTs秒', + L : 'YYYY/MM/DD', + LL : 'YYYY年M月D日', + LLL : 'YYYY年M月D日LT', + LLLL : 'YYYY年M月D日LT dddd' + }, + meridiemParse: /午前|午後/i, + isPM : function (input) { + return input === '午後'; + }, + 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年' + } + }); + + //! moment.js locale configuration + //! locale : Boso Jowo (jv) + //! author : Rony Lantip : https://github.com/lantip + //! reference: http://jv.wikipedia.org/wiki/Basa_Jawa + + var jv = moment.defineLocale('jv', { + months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'), + weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'), + weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'), + weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'LT.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] LT', + LLLL : 'dddd, D MMMM YYYY [pukul] LT' + }, + meridiemParse: /enjing|siyang|sonten|ndalu/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'enjing') { + return hour; + } else if (meridiem === 'siyang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sonten' || meridiem === 'ndalu') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'enjing'; + } else if (hours < 15) { + return 'siyang'; + } else if (hours < 19) { + return 'sonten'; + } else { + return 'ndalu'; + } + }, + calendar : { + sameDay : '[Dinten puniko pukul] LT', + nextDay : '[Mbenjang pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kala wingi pukul] LT', + lastWeek : 'dddd [kepengker pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'wonten ing %s', + past : '%s ingkang kepengker', + s : 'sawetawis detik', + m : 'setunggal menit', + mm : '%d menit', + h : 'setunggal jam', + hh : '%d jam', + d : 'sedinten', + dd : '%d dinten', + M : 'sewulan', + MM : '%d wulan', + y : 'setaun', + yy : '%d taun' + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Georgian (ka) + //! author : Irakli Janiashvili : https://github.com/irakli-janiashvili + + function ka__monthsCaseReplace(m, format) { + var months = { + 'nominative': 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'), + 'accusative': 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_') + }, + nounCase = (/D[oD] *MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; + } + function ka__weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'), + 'accusative': 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_') + }, + nounCase = (/(წინა|შემდეგ)/).test(format) ? + 'accusative' : + 'nominative'; + return weekdays[nounCase][m.day()]; + } + + var ka = moment.defineLocale('ka', { + months : ka__monthsCaseReplace, + monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'), + weekdays : ka__weekdaysCaseReplace, + weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'), + weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss 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 წელი' + }, + ordinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/, + 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 + } + }); + + //! moment.js locale configuration + //! locale : khmer (km) + //! author : Kruy Vanna : https://github.com/kruyvanna + + var km = moment.defineLocale('km', { + months: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + monthsShort: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + longDateFormat: { + LT: 'HH:mm', + LTS : 'LT:ss', + 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: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : korean (ko) + //! + //! authors + //! + //! - Kyungwook, Park : https://github.com/kyungw00k + //! - Jeeeyul Lee <jeeeyul@gmail.com> + + var ko = moment.defineLocale('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시 m분', + LTS : 'A h시 m분 s초', + L : 'YYYY.MM.DD', + LL : 'YYYY년 MMMM D일', + LLL : 'YYYY년 MMMM D일 LT', + LLLL : 'YYYY년 MMMM D일 dddd LT' + }, + 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년' + }, + ordinalParse : /\d{1,2}일/, + ordinal : '%d일', + meridiemParse : /오전|오후/, + isPM : function (token) { + return token === '오후'; + }, + meridiem : function (hour, minute, isUpper) { + return hour < 12 ? '오전' : '오후'; + } + }); + + //! moment.js locale configuration + //! locale : Luxembourgish (lb) + //! author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz + + function lb__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eng Minutt', 'enger Minutt'], + 'h': ['eng Stonn', 'enger Stonn'], + 'd': ['een Dag', 'engem Dag'], + 'M': ['ee Mount', 'engem Mount'], + 'y': ['ee Joer', 'engem Joer'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; + } + function processFutureTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'a ' + string; + } + return 'an ' + string; + } + function processPastTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'viru ' + string; + } + return 'virun ' + string; + } + /** + * Returns true if the word before the given number loses the '-n' ending. + * e.g. 'an 10 Deeg' but 'a 5 Deeg' + * + * @param number {integer} + * @returns {boolean} + */ + function eifelerRegelAppliesToNumber(number) { + number = parseInt(number, 10); + if (isNaN(number)) { + return false; + } + if (number < 0) { + // Negative Number --> always true + return true; + } else if (number < 10) { + // Only 1 digit + if (4 <= number && number <= 7) { + return true; + } + return false; + } else if (number < 100) { + // 2 digits + var lastDigit = number % 10, firstDigit = number / 10; + if (lastDigit === 0) { + return eifelerRegelAppliesToNumber(firstDigit); + } + return eifelerRegelAppliesToNumber(lastDigit); + } else if (number < 10000) { + // 3 or 4 digits --> recursively check first digit + while (number >= 10) { + number = number / 10; + } + return eifelerRegelAppliesToNumber(number); + } else { + // Anything larger than 4 digits: recursively check first n-3 digits + number = number / 1000; + return eifelerRegelAppliesToNumber(number); + } + } + + var lb = moment.defineLocale('lb', { + months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'), + weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'), + weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'), + longDateFormat: { + LT: 'H:mm [Auer]', + LTS: 'H:mm:ss [Auer]', + L: 'DD.MM.YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY LT', + LLLL: 'dddd, D. MMMM YYYY LT' + }, + calendar: { + sameDay: '[Haut um] LT', + sameElse: 'L', + nextDay: '[Muer um] LT', + nextWeek: 'dddd [um] LT', + lastDay: '[Gëschter um] LT', + lastWeek: function () { + // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule + switch (this.day()) { + case 2: + case 4: + return '[Leschten] dddd [um] LT'; + default: + return '[Leschte] dddd [um] LT'; + } + } + }, + relativeTime : { + future : processFutureTime, + past : processPastTime, + s : 'e puer Sekonnen', + m : lb__processRelativeTime, + mm : '%d Minutten', + h : lb__processRelativeTime, + hh : '%d Stonnen', + d : lb__processRelativeTime, + dd : '%d Deeg', + M : lb__processRelativeTime, + MM : '%d Méint', + y : lb__processRelativeTime, + yy : '%d Joer' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Lithuanian (lt) + //! author : Mindaugas Mozūras : https://github.com/mmozuras + + var lt__units = { + 'm' : 'minutė_minutės_minutę', + 'mm': 'minutės_minučių_minutes', + 'h' : 'valanda_valandos_valandą', + 'hh': 'valandos_valandų_valandas', + 'd' : 'diena_dienos_dieną', + 'dd': 'dienos_dienų_dienas', + 'M' : 'mėnuo_mėnesio_mėnesį', + 'MM': 'mėnesiai_mėnesių_mėnesius', + 'y' : 'metai_metų_metus', + 'yy': 'metai_metų_metus' + }, + weekDays = 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'); + function translateSeconds(number, withoutSuffix, key, isFuture) { + if (withoutSuffix) { + return 'kelios sekundės'; + } else { + return isFuture ? 'kelių sekundžių' : 'kelias sekundes'; + } + } + function translateSingular(number, withoutSuffix, key, isFuture) { + return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]); + } + function special(number) { + return number % 10 === 0 || (number > 10 && number < 20); + } + function forms(key) { + return lt__units[key].split('_'); + } + function lt__translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + if (number === 1) { + return result + translateSingular(number, withoutSuffix, key[0], isFuture); + } else if (withoutSuffix) { + return result + (special(number) ? forms(key)[1] : forms(key)[0]); + } else { + if (isFuture) { + return result + forms(key)[1]; + } else { + return result + (special(number) ? forms(key)[1] : forms(key)[2]); + } + } + } + function relativeWeekDay(moment, format) { + var nominative = format.indexOf('dddd HH:mm') === -1, + weekDay = weekDays[moment.day()]; + return nominative ? weekDay : weekDay.substring(0, weekDay.length - 2) + 'į'; + } + + var lt = moment.defineLocale('lt', { + months : 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'), + monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'), + weekdays : relativeWeekDay, + weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'), + weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'YYYY-MM-DD', + LL : 'YYYY [m.] MMMM D [d.]', + LLL : 'YYYY [m.] MMMM D [d.], LT [val.]', + LLLL : 'YYYY [m.] MMMM D [d.], dddd, LT [val.]', + l : 'YYYY-MM-DD', + ll : 'YYYY [m.] MMMM D [d.]', + lll : 'YYYY [m.] MMMM D [d.], LT [val.]', + llll : 'YYYY [m.] MMMM D [d.], ddd, LT [val.]' + }, + calendar : { + sameDay : '[Šiandien] LT', + nextDay : '[Rytoj] LT', + nextWeek : 'dddd LT', + lastDay : '[Vakar] LT', + lastWeek : '[Praėjusį] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : 'po %s', + past : 'prieš %s', + s : translateSeconds, + m : translateSingular, + mm : lt__translate, + h : translateSingular, + hh : lt__translate, + d : translateSingular, + dd : lt__translate, + M : translateSingular, + MM : lt__translate, + y : translateSingular, + yy : lt__translate + }, + ordinalParse: /\d{1,2}-oji/, + ordinal : function (number) { + return number + '-oji'; + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : latvian (lv) + //! author : Kristaps Karlsons : https://github.com/skakri + //! author : Jānis Elmeris : https://github.com/JanisE + + var lv__units = { + 'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'h': 'stundas_stundām_stunda_stundas'.split('_'), + 'hh': 'stundas_stundām_stunda_stundas'.split('_'), + 'd': 'dienas_dienām_diena_dienas'.split('_'), + 'dd': 'dienas_dienām_diena_dienas'.split('_'), + 'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'y': 'gada_gadiem_gads_gadi'.split('_'), + 'yy': 'gada_gadiem_gads_gadi'.split('_') + }; + /** + * @param withoutSuffix boolean true = a length of time; false = before/after a period of time. + */ + function format(forms, number, withoutSuffix) { + if (withoutSuffix) { + // E.g. "21 minūte", "3 minūtes". + return number % 10 === 1 && number !== 11 ? forms[2] : forms[3]; + } else { + // E.g. "21 minūtes" as in "pēc 21 minūtes". + // E.g. "3 minūtēm" as in "pēc 3 minūtēm". + return number % 10 === 1 && number !== 11 ? forms[0] : forms[1]; + } + } + function lv__relativeTimeWithPlural(number, withoutSuffix, key) { + return number + ' ' + format(lv__units[key], number, withoutSuffix); + } + function relativeTimeWithSingular(number, withoutSuffix, key) { + return format(lv__units[key], number, withoutSuffix); + } + function relativeSeconds(number, withoutSuffix) { + return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm'; + } + + var lv = moment.defineLocale('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', + LTS : 'LT:ss', + 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 : 'pēc %s', + past : 'pirms %s', + s : relativeSeconds, + m : relativeTimeWithSingular, + mm : lv__relativeTimeWithPlural, + h : relativeTimeWithSingular, + hh : lv__relativeTimeWithPlural, + d : relativeTimeWithSingular, + dd : lv__relativeTimeWithPlural, + M : relativeTimeWithSingular, + MM : lv__relativeTimeWithPlural, + y : relativeTimeWithSingular, + yy : lv__relativeTimeWithPlural + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Montenegrin (me) + //! author : Miodrag Nikač <miodrag@restartit.me> : https://github.com/miodragnikac + + var me__translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jednog minuta'], + mm: ['minut', 'minuta', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mjesec', 'mjeseca', 'mjeseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = me__translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + me__translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var me = moment.defineLocale('me', { + months: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'], + monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'], + weekdays: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'], + weekdaysShort: ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'], + weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'], + longDateFormat: { + LT: 'H:mm', + LTS : 'LT:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY LT', + LLLL: 'dddd, D. MMMM YYYY LT' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sjutra u] LT', + + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedjelje] [u] LT', + '[prošlog] [ponedjeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srijede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'nekoliko sekundi', + m : me__translator.translate, + mm : me__translator.translate, + h : me__translator.translate, + hh : me__translator.translate, + d : 'dan', + dd : me__translator.translate, + M : 'mjesec', + MM : me__translator.translate, + y : 'godinu', + yy : me__translator.translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : macedonian (mk) + //! author : Borislav Mickov : https://github.com/B0k0 + + var mk = moment.defineLocale('mk', { + months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'), + weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'), + weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + 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 години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : malayalam (ml) + //! author : Floyd Pink : https://github.com/floydpink + + var ml = moment.defineLocale('ml', { + months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'), + monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'), + weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'), + weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'), + weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'), + longDateFormat : { + LT : 'A h:mm -നു', + LTS : 'A h:mm:ss -നു', + 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 വർഷം' + }, + meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i, + isPM : function (input) { + return /^(ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'രാത്രി'; + } else if (hour < 12) { + return 'രാവിലെ'; + } else if (hour < 17) { + return 'ഉച്ച കഴിഞ്ഞ്'; + } else if (hour < 20) { + return 'വൈകുന്നേരം'; + } else { + return 'രാത്രി'; + } + } + }); + + //! moment.js locale configuration + //! locale : Marathi (mr) + //! author : Harshad Kale : https://github.com/kalehv + + var mr__symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + mr__numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var mr = moment.defineLocale('mr', { + months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'), + monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'), + weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm वाजता', + LTS : 'A h:mm:ss वाजता', + 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 mr__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return mr__symbolMap[match]; + }); + }, + meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात्री') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सकाळी') { + return hour; + } else if (meridiem === 'दुपारी') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'सायंकाळी') { + return hour + 12; + } + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Bahasa Malaysia (ms-MY) + //! author : Weldan Jamili : https://github.com/weldan + + var ms_my = moment.defineLocale('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', + LTS : 'LT.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] LT', + LLLL : 'dddd, D MMMM YYYY [pukul] LT' + }, + meridiemParse: /pagi|tengahari|petang|malam/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'tengahari') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'petang' || meridiem === 'malam') { + return hour + 12; + } + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Burmese (my) + //! author : Squar team, mysquar.com + + var my__symbolMap = { + '1': '၁', + '2': '၂', + '3': '၃', + '4': '၄', + '5': '၅', + '6': '၆', + '7': '၇', + '8': '၈', + '9': '၉', + '0': '၀' + }, my__numberMap = { + '၁': '1', + '၂': '2', + '၃': '3', + '၄': '4', + '၅': '5', + '၆': '6', + '၇': '7', + '၈': '8', + '၉': '9', + '၀': '0' + }; + + var my = moment.defineLocale('my', { + months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'), + monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'), + weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'), + weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + + longDateFormat: { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + 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 my__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return my__symbolMap[match]; + }); + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : norwegian bokmål (nb) + //! authors : Espen Hovlandsdal : https://github.com/rexxars + //! Sigurd Gartmann : https://github.com/sigurdga + + var nb = moment.defineLocale('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_tirs_ons_tors_fre_lør'.split('_'), + weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), + longDateFormat : { + LT : 'H.mm', + LTS : 'LT.ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] LT', + LLLL : 'dddd D. MMMM YYYY [kl.] LT' + }, + calendar : { + sameDay: '[i dag kl.] LT', + nextDay: '[i morgen kl.] LT', + nextWeek: 'dddd [kl.] LT', + lastDay: '[i går kl.] LT', + lastWeek: '[forrige] dddd [kl.] 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' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : nepali/nepalese + //! author : suvash : https://github.com/suvash + + var ne__symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + ne__numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var ne = moment.defineLocale('ne', { + months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'), + monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'), + weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'), + weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'), + weekdaysMin : 'आइ._सो._मङ्_बु._बि._शु._श.'.split('_'), + longDateFormat : { + LT : 'Aको h:mm बजे', + LTS : 'Aको h:mm:ss बजे', + 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 ne__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ne__symbolMap[match]; + }); + }, + meridiemParse: /राती|बिहान|दिउँसो|बेलुका|साँझ|राती/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'राती') { + return hour < 3 ? hour : hour + 12; + } else if (meridiem === 'बिहान') { + return hour; + } else if (meridiem === 'दिउँसो') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'बेलुका' || meridiem === 'साँझ') { + return hour + 12; + } + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : dutch (nl) + //! author : Joris Röling : https://github.com/jjupiter + + var nl__monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_'), + nl__monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_'); + + var nl = moment.defineLocale('nl', { + months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return nl__monthsShortWithoutDots[m.month()]; + } else { + return nl__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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(ste|de)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : norwegian nynorsk (nn) + //! author : https://github.com/mechuwind + + var nn = moment.defineLocale('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', + LTS : 'LT:ss', + L : 'DD.MM.YYYY', + 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åande] dddd [klokka] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : 'for %s sidan', + s : 'nokre sekund', + m : 'eit minutt', + mm : '%d minutt', + h : 'ein time', + hh : '%d timar', + d : 'ein dag', + dd : '%d dagar', + M : 'ein månad', + MM : '%d månader', + y : 'eit år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : 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 pl__plural(n) { + return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1); + } + function pl__translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'minuta' : 'minutę'; + case 'mm': + return result + (pl__plural(number) ? 'minuty' : 'minut'); + case 'h': + return withoutSuffix ? 'godzina' : 'godzinę'; + case 'hh': + return result + (pl__plural(number) ? 'godziny' : 'godzin'); + case 'MM': + return result + (pl__plural(number) ? 'miesiące' : 'miesięcy'); + case 'yy': + return result + (pl__plural(number) ? 'lata' : 'lat'); + } + } + + var pl = moment.defineLocale('pl', { + months : function (momentToFormat, format) { + if (format === '') { + // Hack: if format empty we know this is used to generate + // RegExp by moment. Give then back both valid forms of months + // in RegExp ready format. + return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')'; + } else 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', + LTS : 'LT:ss', + 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 : pl__translate, + mm : pl__translate, + h : pl__translate, + hh : pl__translate, + d : '1 dzień', + dd : '%d dni', + M : 'miesiąc', + MM : pl__translate, + y : 'rok', + yy : pl__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : brazilian portuguese (pt-br) + //! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira + + var pt_br = moment.defineLocale('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', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY [às] LT', + LLLL : 'dddd, D [de] MMMM [de] YYYY [às] 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' + }, + ordinalParse: /\d{1,2}º/, + ordinal : '%dº' + }); + + //! moment.js locale configuration + //! locale : portuguese (pt) + //! author : Jefferson : https://github.com/jalex79 + + var pt = moment.defineLocale('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', + LTS : 'LT:ss', + 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 : 'há %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' + }, + ordinalParse: /\d{1,2}º/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : romanian (ro) + //! author : Vlad Gurdiga : https://github.com/gurdiga + //! author : Valentin Agachi : https://github.com/avaly + + function ro__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': 'minute', + 'hh': 'ore', + 'dd': 'zile', + 'MM': 'luni', + 'yy': 'ani' + }, + separator = ' '; + if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) { + separator = ' de '; + } + return number + separator + format[key]; + } + + var ro = moment.defineLocale('ro', { + months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'), + monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._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', + LTS : 'LT:ss', + 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 : ro__relativeTimeWithPlural, + h : 'o oră', + hh : ro__relativeTimeWithPlural, + d : 'o zi', + dd : ro__relativeTimeWithPlural, + M : 'o lună', + MM : ro__relativeTimeWithPlural, + y : 'un an', + yy : ro__relativeTimeWithPlural + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : russian (ru) + //! author : Viktorminator : https://github.com/Viktorminator + //! Author : Menelion Elensúle : https://github.com/Oire + + function ru__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 ru__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут', + 'hh': 'час_часа_часов', + 'dd': 'день_дня_дней', + 'MM': 'месяц_месяца_месяцев', + 'yy': 'год_года_лет' + }; + if (key === 'm') { + return withoutSuffix ? 'минута' : 'минуту'; + } + else { + return number + ' ' + ru__plural(format[key], +number); + } + } + function ru__monthsCaseReplace(m, format) { + var months = { + 'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + 'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_') + }, + nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; + } + function ru__monthsShortCaseReplace(m, format) { + var monthsShort = { + 'nominative': 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'), + 'accusative': 'янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек'.split('_') + }, + nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return monthsShort[nounCase][m.month()]; + } + function ru__weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), + 'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_') + }, + nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/).test(format) ? + 'accusative' : + 'nominative'; + return weekdays[nounCase][m.day()]; + } + + var ru = moment.defineLocale('ru', { + months : ru__monthsCaseReplace, + monthsShort : ru__monthsShortCaseReplace, + weekdays : ru__weekdaysCaseReplace, + weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + monthsParse : [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[й|я]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i], + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 (now) { + if (now.week() !== this.week()) { + 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'; + } + } else { + if (this.day() === 2) { + return '[Во] dddd [в] LT'; + } else { + return '[В] dddd [в] LT'; + } + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'через %s', + past : '%s назад', + s : 'несколько секунд', + m : ru__relativeTimeWithPlural, + mm : ru__relativeTimeWithPlural, + h : 'час', + hh : ru__relativeTimeWithPlural, + d : 'день', + dd : ru__relativeTimeWithPlural, + M : 'месяц', + MM : ru__relativeTimeWithPlural, + y : 'год', + yy : ru__relativeTimeWithPlural + }, + meridiemParse: /ночи|утра|дня|вечера/i, + isPM : function (input) { + return /^(дня|вечера)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночи'; + } else if (hour < 12) { + return 'утра'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечера'; + } + }, + ordinalParse: /\d{1,2}-(й|го|я)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Sinhalese (si) + //! author : Sampath Sitinamaluwa : https://github.com/sampathsris + + var si = moment.defineLocale('si', { + months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'), + monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'), + weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'), + weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්රහ_සිකු_සෙන'.split('_'), + weekdaysMin : 'ඉ_ස_අ_බ_බ්ර_සි_සෙ'.split('_'), + longDateFormat : { + LT : 'a h:mm', + LTS : 'a h:mm:ss', + L : 'YYYY/MM/DD', + LL : 'YYYY MMMM D', + LLL : 'YYYY MMMM D, LT', + LLLL : 'YYYY MMMM D [වැනි] dddd, LTS' + }, + 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' + }, + ordinalParse: /\d{1,2} වැනි/, + ordinal : function (number) { + return number + ' වැනි'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'ප.ව.' : 'පස් වරු'; + } else { + return isLower ? 'පෙ.ව.' : 'පෙර වරු'; + } + } + }); + + //! moment.js locale configuration + //! locale : slovak (sk) + //! author : Martin Minka : https://github.com/k2s + //! based on work of petrbela : https://github.com/petrbela + + var sk__months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_'), + sk__monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_'); + function sk__plural(n) { + return (n > 1) && (n < 5); + } + function sk__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 + (sk__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 + (sk__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 + (sk__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 + (sk__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 + (sk__plural(number) ? 'roky' : 'rokov'); + } else { + return result + 'rokmi'; + } + break; + } + } + + var sk = moment.defineLocale('sk', { + months : sk__months, + monthsShort : sk__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; + }(sk__months, sk__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', + LTS : 'LT:ss', + 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 : sk__translate, + m : sk__translate, + mm : sk__translate, + h : sk__translate, + hh : sk__translate, + d : sk__translate, + dd : sk__translate, + M : sk__translate, + MM : sk__translate, + y : sk__translate, + yy : sk__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : slovenian (sl) + //! author : Robert Sedovšek : https://github.com/sedovsek + + function sl__processRelativeTime(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami'; + case 'm': + return withoutSuffix ? 'ena minuta' : 'eno minuto'; + case 'mm': + if (number === 1) { + result += withoutSuffix ? 'minuta' : 'minuto'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'minuti' : 'minutama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'minute' : 'minutami'; + } else { + result += withoutSuffix || isFuture ? 'minut' : 'minutami'; + } + return result; + case 'h': + return withoutSuffix ? 'ena ura' : 'eno uro'; + case 'hh': + if (number === 1) { + result += withoutSuffix ? 'ura' : 'uro'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'uri' : 'urama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'ure' : 'urami'; + } else { + result += withoutSuffix || isFuture ? 'ur' : 'urami'; + } + return result; + case 'd': + return withoutSuffix || isFuture ? 'en dan' : 'enim dnem'; + case 'dd': + if (number === 1) { + result += withoutSuffix || isFuture ? 'dan' : 'dnem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'dni' : 'dnevoma'; + } else { + result += withoutSuffix || isFuture ? 'dni' : 'dnevi'; + } + return result; + case 'M': + return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem'; + case 'MM': + if (number === 1) { + result += withoutSuffix || isFuture ? 'mesec' : 'mesecem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'meseca' : 'mesecema'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'mesece' : 'meseci'; + } else { + result += withoutSuffix || isFuture ? 'mesecev' : 'meseci'; + } + return result; + case 'y': + return withoutSuffix || isFuture ? 'eno leto' : 'enim letom'; + case 'yy': + if (number === 1) { + result += withoutSuffix || isFuture ? 'leto' : 'letom'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'leti' : 'letoma'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'leta' : 'leti'; + } else { + result += withoutSuffix || isFuture ? 'let' : 'leti'; + } + return result; + } + } + + var sl = moment.defineLocale('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', + LTS : 'LT:ss', + 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: + return '[prejšnjo] [nedeljo] [ob] LT'; + case 3: + return '[prejšnjo] [sredo] [ob] LT'; + case 6: + return '[prejšnjo] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prejšnji] dddd [ob] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'čez %s', + past : 'pred %s', + s : sl__processRelativeTime, + m : sl__processRelativeTime, + mm : sl__processRelativeTime, + h : sl__processRelativeTime, + hh : sl__processRelativeTime, + d : sl__processRelativeTime, + dd : sl__processRelativeTime, + M : sl__processRelativeTime, + MM : sl__processRelativeTime, + y : sl__processRelativeTime, + yy : sl__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Albanian (sq) + //! author : Flakërim Ismani : https://github.com/flakerimi + //! author: Menelion Elensúle: https://github.com/Oire (tests) + //! author : Oerd Cukalla : https://github.com/oerd (fixes) + + var sq = moment.defineLocale('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 Martë_E Mërkurë_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('_'), + meridiemParse: /PD|MD/, + isPM: function (input) { + return input.charAt(0) === 'M'; + }, + meridiem : function (hours, minutes, isLower) { + return hours < 12 ? 'PD' : 'MD'; + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : '[Nesër në] LT', + nextWeek : 'dddd [në] LT', + lastDay : '[Dje në] LT', + lastWeek : 'dddd [e kaluar në] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'në %s', + past : '%s më parë', + s : 'disa sekonda', + m : 'një minutë', + mm : '%d minuta', + h : 'një orë', + hh : '%d orë', + d : 'një ditë', + dd : '%d ditë', + M : 'një muaj', + MM : '%d muaj', + y : 'një vit', + yy : '%d vite' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Serbian-cyrillic (sr-cyrl) + //! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + + var sr_cyrl__translator = { + words: { //Different grammatical cases + m: ['један минут', 'једне минуте'], + mm: ['минут', 'минуте', 'минута'], + h: ['један сат', 'једног сата'], + hh: ['сат', 'сата', 'сати'], + dd: ['дан', 'дана', 'дана'], + MM: ['месец', 'месеца', 'месеци'], + yy: ['година', 'године', 'година'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = sr_cyrl__translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + sr_cyrl__translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var sr_cyrl = moment.defineLocale('sr-cyrl', { + months: ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'], + monthsShort: ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'], + weekdays: ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'], + weekdaysShort: ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'], + weekdaysMin: ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'], + longDateFormat: { + LT: 'H:mm', + LTS : 'LT:ss', + 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: function () { + switch (this.day()) { + case 0: + return '[у] [недељу] [у] LT'; + case 3: + return '[у] [среду] [у] LT'; + case 6: + return '[у] [суботу] [у] LT'; + case 1: + case 2: + case 4: + case 5: + return '[у] dddd [у] LT'; + } + }, + lastDay : '[јуче у] LT', + lastWeek : function () { + var lastWeekDays = [ + '[прошле] [недеље] [у] LT', + '[прошлог] [понедељка] [у] LT', + '[прошлог] [уторка] [у] LT', + '[прошле] [среде] [у] LT', + '[прошлог] [четвртка] [у] LT', + '[прошлог] [петка] [у] LT', + '[прошле] [суботе] [у] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'за %s', + past : 'пре %s', + s : 'неколико секунди', + m : sr_cyrl__translator.translate, + mm : sr_cyrl__translator.translate, + h : sr_cyrl__translator.translate, + hh : sr_cyrl__translator.translate, + d : 'дан', + dd : sr_cyrl__translator.translate, + M : 'месец', + MM : sr_cyrl__translator.translate, + y : 'годину', + yy : sr_cyrl__translator.translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Serbian-latin (sr) + //! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + + var sr__translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jedne minute'], + mm: ['minut', 'minute', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mesec', 'meseca', 'meseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = sr__translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + sr__translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var sr = moment.defineLocale('sr', { + months: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'], + monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'], + weekdays: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'], + weekdaysShort: ['ned.', 'pon.', 'uto.', 'sre.', 'čet.', 'pet.', 'sub.'], + weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'], + longDateFormat: { + LT: 'H:mm', + LTS : 'LT:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY LT', + LLLL: 'dddd, D. MMMM YYYY LT' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sutra u] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedelju] [u] LT'; + case 3: + return '[u] [sredu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedelje] [u] LT', + '[prošlog] [ponedeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'pre %s', + s : 'nekoliko sekundi', + m : sr__translator.translate, + mm : sr__translator.translate, + h : sr__translator.translate, + hh : sr__translator.translate, + d : 'dan', + dd : sr__translator.translate, + M : 'mesec', + MM : sr__translator.translate, + y : 'godinu', + yy : sr__translator.translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : swedish (sv) + //! author : Jens Alm : https://github.com/ulmus + + var sv = moment.defineLocale('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', + LTS : 'LT:ss', + 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: '[På] dddd LT', + lastWeek: '[I] dddd[s] 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' + }, + ordinalParse: /\d{1,2}(e|a)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : tamil (ta) + //! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404 + + var ta = moment.defineLocale('ta', { + months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'), + weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'), + weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 ஆண்டுகள்' + }, + ordinalParse: /\d{1,2}வது/, + ordinal : function (number) { + return number + 'வது'; + }, + // refer http://ta.wikipedia.org/s/1er1 + meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/, + meridiem : function (hour, minute, isLower) { + if (hour < 2) { + return ' யாமம்'; + } else if (hour < 6) { + return ' வைகறை'; // வைகறை + } else if (hour < 10) { + return ' காலை'; // காலை + } else if (hour < 14) { + return ' நண்பகல்'; // நண்பகல் + } else if (hour < 18) { + return ' எற்பாடு'; // எற்பாடு + } else if (hour < 22) { + return ' மாலை'; // மாலை + } else { + return ' யாமம்'; + } + }, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'யாமம்') { + return hour < 2 ? hour : hour + 12; + } else if (meridiem === 'வைகறை' || meridiem === 'காலை') { + return hour; + } else if (meridiem === 'நண்பகல்') { + return hour >= 10 ? hour : hour + 12; + } else { + return hour + 12; + } + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : thai (th) + //! author : Kridsada Thanabulpong : https://github.com/sirn + + var th = moment.defineLocale('th', { + months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'), + monthsShort : 'มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา'.split('_'), + weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'), + weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference + weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'), + longDateFormat : { + LT : 'H นาฬิกา m นาที', + LTS : 'LT s วินาที', + L : 'YYYY/MM/DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY เวลา LT', + LLLL : 'วันddddที่ D MMMM YYYY เวลา LT' + }, + meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/, + isPM: function (input) { + return input === 'หลังเที่ยง'; + }, + 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 ปี' + } + }); + + //! moment.js locale configuration + //! locale : Tagalog/Filipino (tl-ph) + //! author : Dan Hagman + + var tl_ph = moment.defineLocale('tl-ph', { + months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'), + monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'), + weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'), + weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'), + weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'MM/D/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY LT', + LLLL : 'dddd, MMMM DD, YYYY LT' + }, + calendar : { + sameDay: '[Ngayon sa] LT', + nextDay: '[Bukas sa] LT', + nextWeek: 'dddd [sa] LT', + lastDay: '[Kahapon sa] LT', + lastWeek: 'dddd [huling linggo] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'sa loob ng %s', + past : '%s ang nakalipas', + s : 'ilang segundo', + m : 'isang minuto', + mm : '%d minuto', + h : 'isang oras', + hh : '%d oras', + d : 'isang araw', + dd : '%d araw', + M : 'isang buwan', + MM : '%d buwan', + y : 'isang taon', + yy : '%d taon' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : turkish (tr) + //! authors : Erhan Gundogan : https://github.com/erhangundogan, + //! Burak Yiğit Kaya: https://github.com/BYK + + var tr__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 tr = moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/, + 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 + (tr__suffixes[a] || tr__suffixes[b] || tr__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. + } + }); + + //! moment.js locale configuration + //! locale : Morocco Central Atlas Tamaziɣt in Latin (tzm-latn) + //! author : Abdel Said : https://github.com/abdelsaid + + var tzm_latn = moment.defineLocale('tzm-latn', { + 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', + LTS : 'LT:ss', + 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. + } + }); + + //! moment.js locale configuration + //! locale : Morocco Central Atlas Tamaziɣt (tzm) + //! author : Abdel Said : https://github.com/abdelsaid + + var tzm = moment.defineLocale('tzm', { + months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS: 'LT:ss', + 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. + } + }); + + //! moment.js locale configuration + //! locale : ukrainian (uk) + //! author : zemlanin : https://github.com/zemlanin + //! Author : Menelion Elensúle : https://github.com/Oire + + function uk__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 uk__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 + ' ' + uk__plural(format[key], +number); + } + } + function uk__monthsCaseReplace(m, format) { + var months = { + 'nominative': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_'), + 'accusative': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_') + }, + nounCase = (/D[oD]? *MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; + } + function uk__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'; + }; + } + + var uk = moment.defineLocale('uk', { + months : uk__monthsCaseReplace, + monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'), + weekdays : uk__weekdaysCaseReplace, + weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : uk__relativeTimeWithPlural, + mm : uk__relativeTimeWithPlural, + h : 'годину', + hh : uk__relativeTimeWithPlural, + d : 'день', + dd : uk__relativeTimeWithPlural, + M : 'місяць', + MM : uk__relativeTimeWithPlural, + y : 'рік', + yy : uk__relativeTimeWithPlural + }, + // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason + meridiemParse: /ночі|ранку|дня|вечора/, + isPM: function (input) { + return /^(дня|вечора)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночі'; + } else if (hour < 12) { + return 'ранку'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечора'; + } + }, + ordinalParse: /\d{1,2}-(й|го)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : uzbek (uz) + //! author : Sardor Muminov : https://github.com/muminoff + + var uz = moment.defineLocale('uz', { + months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'), + weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'), + weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'), + weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'D MMMM YYYY, dddd 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 : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : vietnamese (vi) + //! author : Bang Nguyen : https://github.com/bangnk + + var vi = moment.defineLocale('vi', { + months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'), + monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'), + weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'), + weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM [năm] YYYY', + LLL : 'D MMMM [năm] YYYY LT', + LLLL : 'dddd, D MMMM [năm] YYYY LT', + l : 'DD/M/YYYY', + ll : 'D MMM YYYY', + lll : 'D MMM YYYY LT', + llll : 'ddd, D MMM YYYY LT' + }, + calendar : { + sameDay: '[Hôm nay lúc] LT', + nextDay: '[Ngày mai lúc] LT', + nextWeek: 'dddd [tuần tới lúc] LT', + lastDay: '[Hôm qua lúc] LT', + lastWeek: 'dddd [tuần rồi lúc] LT', + sameElse: 'L' + }, + relativeTime : { + future : '%s tới', + past : '%s trước', + s : 'vài giây', + m : 'một phút', + mm : '%d phút', + h : 'một giờ', + hh : '%d giờ', + d : 'một ngày', + dd : '%d ngày', + M : 'một tháng', + MM : '%d tháng', + y : 'một năm', + yy : '%d năm' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : chinese (zh-cn) + //! author : suupic : https://github.com/suupic + //! author : Zeno Zeng : https://github.com/zenozeng + + var zh_cn = moment.defineLocale('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分', + LTS : 'Ah点m分s秒', + L : 'YYYY-MM-DD', + LL : 'YYYY年MMMD日', + LLL : 'YYYY年MMMD日LT', + LLLL : 'YYYY年MMMD日ddddLT', + l : 'YYYY-MM-DD', + ll : 'YYYY年MMMD日', + lll : 'YYYY年MMMD日LT', + llll : 'YYYY年MMMD日ddddLT' + }, + meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '凌晨' || meridiem === '早上' || + meridiem === '上午') { + return hour; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } else { + // '中午' + return hour >= 11 ? hour : hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 600) { + return '凌晨'; + } else if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : function () { + return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT'; + }, + nextDay : function () { + return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT'; + }, + lastDay : function () { + return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT'; + }, + nextWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment().startOf('week'); + prefix = this.unix() - startOfWeek.unix() >= 7 * 24 * 3600 ? '[下]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + lastWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment().startOf('week'); + prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + sameElse : 'LL' + }, + ordinalParse: /\d{1,2}(日|月|周)/, + 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 年' + }, + week : { + // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 + 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. + } + }); + + //! moment.js locale configuration + //! locale : traditional chinese (zh-tw) + //! author : Ben : https://github.com/ben-lin + + var zh_tw = moment.defineLocale('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分', + LTS : 'Ah點m分s秒', + 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' + }, + meridiemParse: /早上|上午|中午|下午|晚上/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '早上' || meridiem === '上午') { + return hour; + } else if (meridiem === '中午') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + ordinalParse: /\d{1,2}(日|月|週)/, + 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年' + } + }); + + + +}));
\ No newline at end of file diff --git a/bower_components/moment/min/moment-with-locales.js b/bower_components/moment/min/moment-with-locales.js new file mode 100644 index 0000000..61145c0 --- /dev/null +++ b/bower_components/moment/min/moment-with-locales.js @@ -0,0 +1,9737 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + global.moment = factory() +}(this, function () { 'use strict'; + + var hookCallback; + + function utils_hooks__hooks () { + return hookCallback.apply(null, arguments); + } + + // This is done to register the method called with moment() + // without creating circular dependencies. + function setHookCallback (callback) { + hookCallback = callback; + } + + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; + } + + function isDate(input) { + return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]'; + } + + function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; + } + + function hasOwnProp(a, b) { + return Object.prototype.hasOwnProperty.call(a, b); + } + + function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } + } + + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } + + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; + } + + return a; + } + + function create_utc__createUTC (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, true).utc(); + } + + function defaultParsingFlags() { + // We need to deep clone this object. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso : false + }; + } + + function getParsingFlags(m) { + if (m._pf == null) { + m._pf = defaultParsingFlags(); + } + return m._pf; + } + + function valid__isValid(m) { + if (m._isValid == null) { + var flags = getParsingFlags(m); + m._isValid = !isNaN(m._d.getTime()) && + flags.overflow < 0 && + !flags.empty && + !flags.invalidMonth && + !flags.nullInput && + !flags.invalidFormat && + !flags.userInvalidated; + + if (m._strict) { + m._isValid = m._isValid && + flags.charsLeftOver === 0 && + flags.unusedTokens.length === 0 && + flags.bigHour === undefined; + } + } + return m._isValid; + } + + function valid__createInvalid (flags) { + var m = create_utc__createUTC(NaN); + if (flags != null) { + extend(getParsingFlags(m), flags); + } + else { + getParsingFlags(m).userInvalidated = true; + } + + return m; + } + + var momentProperties = utils_hooks__hooks.momentProperties = []; + + function copyConfig(to, from) { + var i, prop, val; + + if (typeof from._isAMomentObject !== 'undefined') { + to._isAMomentObject = from._isAMomentObject; + } + if (typeof from._i !== 'undefined') { + to._i = from._i; + } + if (typeof from._f !== 'undefined') { + to._f = from._f; + } + if (typeof from._l !== 'undefined') { + to._l = from._l; + } + if (typeof from._strict !== 'undefined') { + to._strict = from._strict; + } + if (typeof from._tzm !== 'undefined') { + to._tzm = from._tzm; + } + if (typeof from._isUTC !== 'undefined') { + to._isUTC = from._isUTC; + } + if (typeof from._offset !== 'undefined') { + to._offset = from._offset; + } + if (typeof from._pf !== 'undefined') { + to._pf = getParsingFlags(from); + } + if (typeof from._locale !== 'undefined') { + to._locale = from._locale; + } + + if (momentProperties.length > 0) { + for (i in momentProperties) { + prop = momentProperties[i]; + val = from[prop]; + if (typeof val !== 'undefined') { + to[prop] = val; + } + } + } + + return to; + } + + var updateInProgress = false; + + // Moment prototype object + function Moment(config) { + copyConfig(this, config); + this._d = new Date(+config._d); + // Prevent infinite loop in case updateOffset creates new moment + // objects. + if (updateInProgress === false) { + updateInProgress = true; + utils_hooks__hooks.updateOffset(this); + updateInProgress = false; + } + } + + function isMoment (obj) { + return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); + } + + function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; + + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + if (coercedNumber >= 0) { + value = Math.floor(coercedNumber); + } else { + value = Math.ceil(coercedNumber); + } + } + + return value; + } + + function compareArrays(array1, array2, dontConvert) { + 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 ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; + } + + function Locale() { + } + + var locales = {}; + var globalLocale; + + function normalizeLocale(key) { + return key ? key.toLowerCase().replace('_', '-') : key; + } + + // pick the locale from the array + // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each + // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root + function chooseLocale(names) { + var i = 0, j, next, locale, split; + + while (i < names.length) { + split = normalizeLocale(names[i]).split('-'); + j = split.length; + next = normalizeLocale(names[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + locale = loadLocale(split.slice(0, j).join('-')); + if (locale) { + return locale; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return null; + } + + function loadLocale(name) { + var oldLocale = null; + // TODO: Find a better way to register and load all the locales in Node + if (!locales[name] && typeof module !== 'undefined' && + module && module.exports) { + try { + oldLocale = globalLocale._abbr; + require('./locale/' + name); + // because defineLocale currently also sets the global locale, we + // want to undo that for lazy loaded locales + locale_locales__getSetGlobalLocale(oldLocale); + } catch (e) { } + } + return locales[name]; + } + + // This function will load locale and then set the global locale. If + // no arguments are passed in, it will simply return the current global + // locale key. + function locale_locales__getSetGlobalLocale (key, values) { + var data; + if (key) { + if (typeof values === 'undefined') { + data = locale_locales__getLocale(key); + } + else { + data = defineLocale(key, values); + } + + if (data) { + // moment.duration._locale = moment._locale = data; + globalLocale = data; + } + } + + return globalLocale._abbr; + } + + function defineLocale (name, values) { + if (values !== null) { + values.abbr = name; + if (!locales[name]) { + locales[name] = new Locale(); + } + locales[name].set(values); + + // backwards compat for now: also set the locale + locale_locales__getSetGlobalLocale(name); + + return locales[name]; + } else { + // useful for testing + delete locales[name]; + return null; + } + } + + // returns locale data + function locale_locales__getLocale (key) { + var locale; + + if (key && key._locale && key._locale._abbr) { + key = key._locale._abbr; + } + + if (!key) { + return globalLocale; + } + + if (!isArray(key)) { + //short-circuit everything else + locale = loadLocale(key); + if (locale) { + return locale; + } + key = [key]; + } + + return chooseLocale(key); + } + + var aliases = {}; + + function addUnitAlias (unit, shorthand) { + var lowerCase = unit.toLowerCase(); + aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit; + } + + function normalizeUnits(units) { + return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined; + } + + function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (hasOwnProp(inputObject, prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; + } + + function makeGetSet (unit, keepTime) { + return function (value) { + if (value != null) { + get_set__set(this, unit, value); + utils_hooks__hooks.updateOffset(this, keepTime); + return this; + } else { + return get_set__get(this, unit); + } + }; + } + + function get_set__get (mom, unit) { + return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); + } + + function get_set__set (mom, unit, value) { + return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } + + // MOMENTS + + function getSet (units, value) { + var unit; + if (typeof units === 'object') { + for (unit in units) { + this.set(unit, units[unit]); + } + } else { + units = normalizeUnits(units); + if (typeof this[units] === 'function') { + return this[units](value); + } + } + return this; + } + + function zeroFill(number, targetLength, forceSign) { + var output = '' + Math.abs(number), + sign = number >= 0; + + while (output.length < targetLength) { + output = '0' + output; + } + return (sign ? (forceSign ? '+' : '') : '-') + output; + } + + var formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g; + + var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; + + var formatFunctions = {}; + + var formatTokenFunctions = {}; + + // token: 'M' + // padded: ['MM', 2] + // ordinal: 'Mo' + // callback: function () { this.month() + 1 } + function addFormatToken (token, padded, ordinal, callback) { + var func = callback; + if (typeof callback === 'string') { + func = function () { + return this[callback](); + }; + } + if (token) { + formatTokenFunctions[token] = func; + } + if (padded) { + formatTokenFunctions[padded[0]] = function () { + return zeroFill(func.apply(this, arguments), padded[1], padded[2]); + }; + } + if (ordinal) { + formatTokenFunctions[ordinal] = function () { + return this.localeData().ordinal(func.apply(this, arguments), token); + }; + } + } + + function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + 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) { + if (!m.isValid()) { + return m.localeData().invalidDate(); + } + + format = expandFormat(format, m.localeData()); + + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } + + return formatFunctions[format](m); + } + + function expandFormat(format, locale) { + var i = 5; + + function replaceLongDateFormatTokens(input) { + return locale.longDateFormat(input) || input; + } + + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } + + return format; + } + + var match1 = /\d/; // 0 - 9 + var match2 = /\d\d/; // 00 - 99 + var match3 = /\d{3}/; // 000 - 999 + var match4 = /\d{4}/; // 0000 - 9999 + var match6 = /[+-]?\d{6}/; // -999999 - 999999 + var match1to2 = /\d\d?/; // 0 - 99 + var match1to3 = /\d{1,3}/; // 0 - 999 + var match1to4 = /\d{1,4}/; // 0 - 9999 + var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 + + var matchUnsigned = /\d+/; // 0 - inf + var matchSigned = /[+-]?\d+/; // -inf - inf + + var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z + + var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 + + // any word (or two) characters or numbers including two/three word month in arabic. + var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i; + + var regexes = {}; + + function addRegexToken (token, regex, strictRegex) { + regexes[token] = typeof regex === 'function' ? regex : function (isStrict) { + return (isStrict && strictRegex) ? strictRegex : regex; + }; + } + + function getParseRegexForToken (token, config) { + if (!hasOwnProp(regexes, token)) { + return new RegExp(unescapeFormat(token)); + } + + return regexes[token](config._strict, config._locale); + } + + // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript + function unescapeFormat(s) { + return s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + }).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + } + + var tokens = {}; + + function addParseToken (token, callback) { + var i, func = callback; + if (typeof token === 'string') { + token = [token]; + } + if (typeof callback === 'number') { + func = function (input, array) { + array[callback] = toInt(input); + }; + } + for (i = 0; i < token.length; i++) { + tokens[token[i]] = func; + } + } + + function addWeekParseToken (token, callback) { + addParseToken(token, function (input, array, config, token) { + config._w = config._w || {}; + callback(input, config._w, config, token); + }); + } + + function addTimeToArrayFromToken(token, input, config) { + if (input != null && hasOwnProp(tokens, token)) { + tokens[token](input, config._a, config, token); + } + } + + var YEAR = 0; + var MONTH = 1; + var DATE = 2; + var HOUR = 3; + var MINUTE = 4; + var SECOND = 5; + var MILLISECOND = 6; + + function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); + } + + // FORMATTING + + addFormatToken('M', ['MM', 2], 'Mo', function () { + return this.month() + 1; + }); + + addFormatToken('MMM', 0, 0, function (format) { + return this.localeData().monthsShort(this, format); + }); + + addFormatToken('MMMM', 0, 0, function (format) { + return this.localeData().months(this, format); + }); + + // ALIASES + + addUnitAlias('month', 'M'); + + // PARSING + + addRegexToken('M', match1to2); + addRegexToken('MM', match1to2, match2); + addRegexToken('MMM', matchWord); + addRegexToken('MMMM', matchWord); + + addParseToken(['M', 'MM'], function (input, array) { + array[MONTH] = toInt(input) - 1; + }); + + addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { + var month = config._locale.monthsParse(input, token, config._strict); + // if we didn't find a month name, mark the date as invalid. + if (month != null) { + array[MONTH] = month; + } else { + getParsingFlags(config).invalidMonth = input; + } + }); + + // LOCALES + + var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'); + function localeMonths (m) { + return this._months[m.month()]; + } + + var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'); + function localeMonthsShort (m) { + return this._monthsShort[m.month()]; + } + + function localeMonthsParse (monthName, format, strict) { + var i, mom, regex; + + if (!this._monthsParse) { + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + } + + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = create_utc__createUTC([2000, i]); + if (strict && !this._longMonthsParse[i]) { + this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); + this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); + } + if (!strict && !this._monthsParse[i]) { + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { + return i; + } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { + return i; + } else if (!strict && this._monthsParse[i].test(monthName)) { + return i; + } + } + } + + // MOMENTS + + function setMonth (mom, value) { + var dayOfMonth; + + // TODO: Move this out of here! + if (typeof value === 'string') { + value = mom.localeData().monthsParse(value); + // TODO: Another silent failure? + if (typeof value !== 'number') { + return mom; + } + } + + dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; + } + + function getSetMonth (value) { + if (value != null) { + setMonth(this, value); + utils_hooks__hooks.updateOffset(this, true); + return this; + } else { + return get_set__get(this, 'Month'); + } + } + + function getDaysInMonth () { + return daysInMonth(this.year(), this.month()); + } + + function checkOverflow (m) { + var overflow; + var a = m._a; + + if (a && getParsingFlags(m).overflow === -2) { + overflow = + a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : + a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : + a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR : + a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : + a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : + a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : + -1; + + if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } + + getParsingFlags(m).overflow = overflow; + } + + return m; + } + + function warn(msg) { + if (utils_hooks__hooks.suppressDeprecationWarnings === false && typeof console !== 'undefined' && console.warn) { + console.warn('Deprecation warning: ' + msg); + } + } + + function deprecate(msg, fn) { + var firstTime = true, + msgWithStack = msg + '\n' + (new Error()).stack; + + return extend(function () { + if (firstTime) { + warn(msgWithStack); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); + } + + var deprecations = {}; + + function deprecateSimple(name, msg) { + if (!deprecations[name]) { + warn(msg); + deprecations[name] = true; + } + } + + utils_hooks__hooks.suppressDeprecationWarnings = false; + + var from_string__isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/; + + var isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/], + ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/], + ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/], + ['GGGG-[W]WW', /\d{4}-W\d{2}/], + ['YYYY-DDD', /\d{4}-\d{3}/] + ]; + + // iso time formats and regexes + var isoTimes = [ + ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/], + ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], + ['HH:mm', /(T| )\d\d:\d\d/], + ['HH', /(T| )\d\d/] + ]; + + var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; + + // date from iso format + function configFromISO(config) { + var i, l, + string = config._i, + match = from_string__isoRegex.exec(string); + + if (match) { + getParsingFlags(config).iso = true; + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(string)) { + // match[5] should be 'T' or undefined + config._f = isoDates[i][0] + (match[6] || ' '); + break; + } + } + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(string)) { + config._f += isoTimes[i][0]; + break; + } + } + if (string.match(matchOffset)) { + config._f += 'Z'; + } + configFromStringAndFormat(config); + } else { + config._isValid = false; + } + } + + // date from iso format or fallback + function configFromString(config) { + var matched = aspNetJsonRegex.exec(config._i); + + if (matched !== null) { + config._d = new Date(+matched[1]); + return; + } + + configFromISO(config); + if (config._isValid === false) { + delete config._isValid; + utils_hooks__hooks.createFromInputFallback(config); + } + } + + utils_hooks__hooks.createFromInputFallback = deprecate( + 'moment construction falls back to js Date. This is ' + + 'discouraged and will be removed in upcoming major ' + + 'release. Please refer to ' + + 'https://github.com/moment/moment/issues/1407 for more info.', + function (config) { + config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); + } + ); + + function createDate (y, m, d, h, M, s, ms) { + //can't just apply() to create a date: + //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply + var date = new Date(y, m, d, h, M, s, ms); + + //the date constructor doesn't accept years < 1970 + if (y < 1970) { + date.setFullYear(y); + } + return date; + } + + function createUTCDate (y) { + var date = new Date(Date.UTC.apply(null, arguments)); + if (y < 1970) { + date.setUTCFullYear(y); + } + return date; + } + + addFormatToken(0, ['YY', 2], 0, function () { + return this.year() % 100; + }); + + addFormatToken(0, ['YYYY', 4], 0, 'year'); + addFormatToken(0, ['YYYYY', 5], 0, 'year'); + addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); + + // ALIASES + + addUnitAlias('year', 'y'); + + // PARSING + + addRegexToken('Y', matchSigned); + addRegexToken('YY', match1to2, match2); + addRegexToken('YYYY', match1to4, match4); + addRegexToken('YYYYY', match1to6, match6); + addRegexToken('YYYYYY', match1to6, match6); + + addParseToken(['YYYY', 'YYYYY', 'YYYYYY'], YEAR); + addParseToken('YY', function (input, array) { + array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input); + }); + + // HELPERS + + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; + } + + function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + } + + // HOOKS + + utils_hooks__hooks.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); + }; + + // MOMENTS + + var getSetYear = makeGetSet('FullYear', false); + + function getIsLeapYear () { + return isLeapYear(this.year()); + } + + addFormatToken('w', ['ww', 2], 'wo', 'week'); + addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); + + // ALIASES + + addUnitAlias('week', 'w'); + addUnitAlias('isoWeek', 'W'); + + // PARSING + + addRegexToken('w', match1to2); + addRegexToken('ww', match1to2, match2); + addRegexToken('W', match1to2); + addRegexToken('WW', match1to2, match2); + + addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { + week[token.substr(0, 1)] = toInt(input); + }); + + // HELPERS + + // 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 = local__createLocal(mom).add(daysToDayOfWeek, 'd'); + return { + week: Math.ceil(adjustedMoment.dayOfYear() / 7), + year: adjustedMoment.year() + }; + } + + // LOCALES + + function localeWeek (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + } + + var defaultLocaleWeek = { + 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 localeFirstDayOfWeek () { + return this._week.dow; + } + + function localeFirstDayOfYear () { + return this._week.doy; + } + + // MOMENTS + + function getSetWeek (input) { + var week = this.localeData().week(this); + return input == null ? week : this.add((input - week) * 7, 'd'); + } + + function getSetISOWeek (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add((input - week) * 7, 'd'); + } + + addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); + + // ALIASES + + addUnitAlias('dayOfYear', 'DDD'); + + // PARSING + + addRegexToken('DDD', match1to3); + addRegexToken('DDDD', match3); + addParseToken(['DDD', 'DDDD'], function (input, array, config) { + config._dayOfYear = toInt(input); + }); + + // HELPERS + + //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday + function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { + var d = createUTCDate(year, 0, 1).getUTCDay(); + var daysToAdd; + var dayOfYear; + + d = d === 0 ? 7 : d; + weekday = weekday != null ? weekday : firstDayOfWeek; + daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); + dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; + + return { + year : dayOfYear > 0 ? year : year - 1, + dayOfYear : dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear + }; + } + + // MOMENTS + + function getSetDayOfYear (input) { + var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); + } + + // Pick the first defined of two or three arguments. + function defaults(a, b, c) { + if (a != null) { + return a; + } + if (b != null) { + return b; + } + return c; + } + + function currentDateArray(config) { + var now = new Date(); + if (config._useUTC) { + return [now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()]; + } + return [now.getFullYear(), now.getMonth(), now.getDate()]; + } + + // 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 configFromArray (config) { + var i, date, input = [], currentDate, yearToUse; + + if (config._d) { + return; + } + + currentDate = currentDateArray(config); + + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); + } + + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = defaults(config._a[YEAR], currentDate[YEAR]); + + if (config._dayOfYear > daysInYear(yearToUse)) { + getParsingFlags(config)._overflowDayOfYear = true; + } + + date = createUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } + + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } + + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } + + // Check for 24:00:00.000 + if (config._a[HOUR] === 24 && + config._a[MINUTE] === 0 && + config._a[SECOND] === 0 && + config._a[MILLISECOND] === 0) { + config._nextDay = true; + config._a[HOUR] = 0; + } + + config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input); + // Apply timezone offset from input. The actual utcOffset can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); + } + + if (config._nextDay) { + config._a[HOUR] = 24; + } + } + + function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp; + + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; + + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year); + week = defaults(w.W, 1); + weekday = defaults(w.E, 1); + } else { + dow = config._locale._week.dow; + doy = config._locale._week.doy; + + weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year); + week = defaults(w.w, 1); + + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < dow) { + ++week; + } + } else if (w.e != null) { + // local weekday -- counting starts from begining of week + weekday = w.e + dow; + } else { + // default to begining of week + weekday = dow; + } + } + temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow); + + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } + + utils_hooks__hooks.ISO_8601 = function () {}; + + // date from string and format string + function configFromStringAndFormat(config) { + // TODO: Move this to another part of the creation flow to prevent circular deps + if (config._f === utils_hooks__hooks.ISO_8601) { + configFromISO(config); + return; + } + + config._a = []; + getParsingFlags(config).empty = true; + + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; + + tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; + + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + getParsingFlags(config).unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + getParsingFlags(config).empty = false; + } + else { + getParsingFlags(config).unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + getParsingFlags(config).unusedTokens.push(token); + } + } + + // add remaining unparsed input length to the string + getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + getParsingFlags(config).unusedInput.push(string); + } + + // clear _12h flag if hour is <= 12 + if (getParsingFlags(config).bigHour === true && + config._a[HOUR] <= 12 && + config._a[HOUR] > 0) { + getParsingFlags(config).bigHour = undefined; + } + // handle meridiem + config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); + + configFromArray(config); + checkOverflow(config); + } + + + function meridiemFixWrap (locale, hour, meridiem) { + var isPm; + + if (meridiem == null) { + // nothing to do + return hour; + } + if (locale.meridiemHour != null) { + return locale.meridiemHour(hour, meridiem); + } else if (locale.isPM != null) { + // Fallback + isPm = locale.isPM(meridiem); + if (isPm && hour < 12) { + hour += 12; + } + if (!isPm && hour === 12) { + hour = 0; + } + return hour; + } else { + // this is not supposed to happen + return hour; + } + } + + function configFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + getParsingFlags(config).invalidFormat = true; + config._d = new Date(NaN); + return; + } + + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = copyConfig({}, config); + if (config._useUTC != null) { + tempConfig._useUTC = config._useUTC; + } + tempConfig._f = config._f[i]; + configFromStringAndFormat(tempConfig); + + if (!valid__isValid(tempConfig)) { + continue; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += getParsingFlags(tempConfig).charsLeftOver; + + //or tokens + currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; + + getParsingFlags(tempConfig).score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } + + extend(config, bestMoment || tempConfig); + } + + function configFromObject(config) { + if (config._d) { + return; + } + + var i = normalizeObjectUnits(config._i); + config._a = [i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond]; + + configFromArray(config); + } + + function createFromConfig (config) { + var input = config._i, + format = config._f, + res; + + config._locale = config._locale || locale_locales__getLocale(config._l); + + if (input === null || (format === undefined && input === '')) { + return valid__createInvalid({nullInput: true}); + } + + if (typeof input === 'string') { + config._i = input = config._locale.preparse(input); + } + + if (isMoment(input)) { + return new Moment(checkOverflow(input)); + } else if (isArray(format)) { + configFromStringAndArray(config); + } else if (format) { + configFromStringAndFormat(config); + } else if (isDate(input)) { + config._d = input; + } else { + configFromInput(config); + } + + res = new Moment(checkOverflow(config)); + if (res._nextDay) { + // Adding is smart enough around DST + res.add(1, 'd'); + res._nextDay = undefined; + } + + return res; + } + + function configFromInput(config) { + var input = config._i; + if (input === undefined) { + config._d = new Date(); + } else if (isDate(input)) { + config._d = new Date(+input); + } else if (typeof input === 'string') { + configFromString(config); + } else if (isArray(input)) { + config._a = map(input.slice(0), function (obj) { + return parseInt(obj, 10); + }); + configFromArray(config); + } else if (typeof(input) === 'object') { + configFromObject(config); + } else if (typeof(input) === 'number') { + // from milliseconds + config._d = new Date(input); + } else { + utils_hooks__hooks.createFromInputFallback(config); + } + } + + function createLocalOrUTC (input, format, locale, strict, isUTC) { + var c = {}; + + if (typeof(locale) === 'boolean') { + strict = locale; + locale = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c._isAMomentObject = true; + c._useUTC = c._isUTC = isUTC; + c._l = locale; + c._i = input; + c._f = format; + c._strict = strict; + + return createFromConfig(c); + } + + function local__createLocal (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, false); + } + + var prototypeMin = deprecate( + 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548', + function () { + var other = local__createLocal.apply(null, arguments); + return other < this ? this : other; + } + ); + + var prototypeMax = deprecate( + 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548', + function () { + var other = local__createLocal.apply(null, arguments); + return other > this ? this : other; + } + ); + + // Pick a moment m from moments so that m[fn](other) is true for all + // other. This relies on the function fn to be transitive. + // + // moments should either be an array of moment objects or an array, whose + // first element is an array of moment objects. + function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return local__createLocal(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (moments[i][fn](res)) { + res = moments[i]; + } + } + return res; + } + + // TODO: Use [].sort instead? + function min () { + var args = [].slice.call(arguments, 0); + + return pickBy('isBefore', args); + } + + function max () { + var args = [].slice.call(arguments, 0); + + return pickBy('isAfter', args); + } + + function Duration (duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + quarters = normalizedInput.quarter || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 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 + + quarters * 3 + + years * 12; + + this._data = {}; + + this._locale = locale_locales__getLocale(); + + this._bubble(); + } + + function isDuration (obj) { + return obj instanceof Duration; + } + + function offset (token, separator) { + addFormatToken(token, 0, 0, function () { + var offset = this.utcOffset(); + var sign = '+'; + if (offset < 0) { + offset = -offset; + sign = '-'; + } + return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2); + }); + } + + offset('Z', ':'); + offset('ZZ', ''); + + // PARSING + + addRegexToken('Z', matchOffset); + addRegexToken('ZZ', matchOffset); + addParseToken(['Z', 'ZZ'], function (input, array, config) { + config._useUTC = true; + config._tzm = offsetFromString(input); + }); + + // HELPERS + + // timezone chunker + // '+10:00' > ['10', '00'] + // '-1530' > ['-15', '30'] + var chunkOffset = /([\+\-]|\d\d)/gi; + + function offsetFromString(string) { + var matches = ((string || '').match(matchOffset) || []); + var chunk = matches[matches.length - 1] || []; + var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0]; + var minutes = +(parts[1] * 60) + toInt(parts[2]); + + return parts[0] === '+' ? minutes : -minutes; + } + + // Return a moment from input, that is local/utc/zone equivalent to model. + function cloneWithOffset(input, model) { + var res, diff; + if (model._isUTC) { + res = model.clone(); + diff = (isMoment(input) || isDate(input) ? +input : +local__createLocal(input)) - (+res); + // Use low-level api, because this fn is low-level api. + res._d.setTime(+res._d + diff); + utils_hooks__hooks.updateOffset(res, false); + return res; + } else { + return local__createLocal(input).local(); + } + return model._isUTC ? local__createLocal(input).zone(model._offset || 0) : local__createLocal(input).local(); + } + + function getDateOffset (m) { + // On Firefox.24 Date#getTimezoneOffset returns a floating point. + // https://github.com/moment/moment/pull/1871 + return -Math.round(m._d.getTimezoneOffset() / 15) * 15; + } + + // HOOKS + + // This function will be called whenever a moment is mutated. + // It is intended to keep the offset in sync with the timezone. + utils_hooks__hooks.updateOffset = function () {}; + + // MOMENTS + + // keepLocalTime = true means only change the timezone, without + // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> + // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset + // +0200, so we adjust the time as needed, to be valid. + // + // Keeping the time actually adds/subtracts (one hour) + // from the actual represented time. That is why we call updateOffset + // a second time. In case it wants us to change the offset again + // _changeInProgress == true case, then we have to adjust, because + // there is no such time in the given timezone. + function getSetOffset (input, keepLocalTime) { + var offset = this._offset || 0, + localAdjust; + if (input != null) { + if (typeof input === 'string') { + input = offsetFromString(input); + } + if (Math.abs(input) < 16) { + input = input * 60; + } + if (!this._isUTC && keepLocalTime) { + localAdjust = getDateOffset(this); + } + this._offset = input; + this._isUTC = true; + if (localAdjust != null) { + this.add(localAdjust, 'm'); + } + if (offset !== input) { + if (!keepLocalTime || this._changeInProgress) { + add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + utils_hooks__hooks.updateOffset(this, true); + this._changeInProgress = null; + } + } + return this; + } else { + return this._isUTC ? offset : getDateOffset(this); + } + } + + function getSetZone (input, keepLocalTime) { + if (input != null) { + if (typeof input !== 'string') { + input = -input; + } + + this.utcOffset(input, keepLocalTime); + + return this; + } else { + return -this.utcOffset(); + } + } + + function setOffsetToUTC (keepLocalTime) { + return this.utcOffset(0, keepLocalTime); + } + + function setOffsetToLocal (keepLocalTime) { + if (this._isUTC) { + this.utcOffset(0, keepLocalTime); + this._isUTC = false; + + if (keepLocalTime) { + this.subtract(getDateOffset(this), 'm'); + } + } + return this; + } + + function setOffsetToParsedOffset () { + if (this._tzm) { + this.utcOffset(this._tzm); + } else if (typeof this._i === 'string') { + this.utcOffset(offsetFromString(this._i)); + } + return this; + } + + function hasAlignedHourOffset (input) { + if (!input) { + input = 0; + } + else { + input = local__createLocal(input).utcOffset(); + } + + return (this.utcOffset() - input) % 60 === 0; + } + + function isDaylightSavingTime () { + return ( + this.utcOffset() > this.clone().month(0).utcOffset() || + this.utcOffset() > this.clone().month(5).utcOffset() + ); + } + + function isDaylightSavingTimeShifted () { + if (this._a) { + var other = this._isUTC ? create_utc__createUTC(this._a) : local__createLocal(this._a); + return this.isValid() && compareArrays(this._a, other.toArray()) > 0; + } + + return false; + } + + function isLocal () { + return !this._isUTC; + } + + function isUtcOffset () { + return this._isUTC; + } + + function isUtc () { + return this._isUTC && this._offset === 0; + } + + var aspNetRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/; + + // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html + // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere + var create__isoRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/; + + function create__createDuration (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + diffRes; + + if (isDuration(input)) { + duration = { + ms : input._milliseconds, + d : input._days, + M : input._months + }; + } else if (typeof input === 'number') { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : 0, + d : toInt(match[DATE]) * sign, + h : toInt(match[HOUR]) * sign, + m : toInt(match[MINUTE]) * sign, + s : toInt(match[SECOND]) * sign, + ms : toInt(match[MILLISECOND]) * sign + }; + } else if (!!(match = create__isoRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : parseIso(match[2], sign), + M : parseIso(match[3], sign), + d : parseIso(match[4], sign), + h : parseIso(match[5], sign), + m : parseIso(match[6], sign), + s : parseIso(match[7], sign), + w : parseIso(match[8], sign) + }; + } else if (duration == null) {// checks for null or undefined + duration = {}; + } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) { + diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to)); + + duration = {}; + duration.ms = diffRes.milliseconds; + duration.M = diffRes.months; + } + + ret = new Duration(duration); + + if (isDuration(input) && hasOwnProp(input, '_locale')) { + ret._locale = input._locale; + } + + return ret; + } + + create__createDuration.fn = Duration.prototype; + + function parseIso (inp, sign) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; + } + + function positiveMomentsDifference(base, other) { + var res = {milliseconds: 0, months: 0}; + + res.months = other.month() - base.month() + + (other.year() - base.year()) * 12; + if (base.clone().add(res.months, 'M').isAfter(other)) { + --res.months; + } + + res.milliseconds = +other - +(base.clone().add(res.months, 'M')); + + return res; + } + + function momentsDifference(base, other) { + var res; + other = cloneWithOffset(other, base); + if (base.isBefore(other)) { + res = positiveMomentsDifference(base, other); + } else { + res = positiveMomentsDifference(other, base); + res.milliseconds = -res.milliseconds; + res.months = -res.months; + } + + return res; + } + + function createAdder(direction, name) { + return function (val, period) { + var dur, tmp; + //invert the arguments, but complain about it + if (period !== null && !isNaN(+period)) { + deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).'); + tmp = val; val = period; period = tmp; + } + + val = typeof val === 'string' ? +val : val; + dur = create__createDuration(val, period); + add_subtract__addSubtract(this, dur, direction); + return this; + }; + } + + function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = duration._days, + months = duration._months; + updateOffset = updateOffset == null ? true : updateOffset; + + if (milliseconds) { + mom._d.setTime(+mom._d + milliseconds * isAdding); + } + if (days) { + get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding); + } + if (months) { + setMonth(mom, get_set__get(mom, 'Month') + months * isAdding); + } + if (updateOffset) { + utils_hooks__hooks.updateOffset(mom, days || months); + } + } + + var add_subtract__add = createAdder(1, 'add'); + var add_subtract__subtract = createAdder(-1, 'subtract'); + + function moment_calendar__calendar (time) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're local/utc/offset or not. + var now = time || local__createLocal(), + sod = cloneWithOffset(now, this).startOf('day'), + diff = this.diff(sod, '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.localeData().calendar(format, this, local__createLocal(now))); + } + + function clone () { + return new Moment(this); + } + + function isAfter (input, units) { + var inputMs; + units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); + if (units === 'millisecond') { + input = isMoment(input) ? input : local__createLocal(input); + return +this > +input; + } else { + inputMs = isMoment(input) ? +input : +local__createLocal(input); + return inputMs < +this.clone().startOf(units); + } + } + + function isBefore (input, units) { + var inputMs; + units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); + if (units === 'millisecond') { + input = isMoment(input) ? input : local__createLocal(input); + return +this < +input; + } else { + inputMs = isMoment(input) ? +input : +local__createLocal(input); + return +this.clone().endOf(units) < inputMs; + } + } + + function isBetween (from, to, units) { + return this.isAfter(from, units) && this.isBefore(to, units); + } + + function isSame (input, units) { + var inputMs; + units = normalizeUnits(units || 'millisecond'); + if (units === 'millisecond') { + input = isMoment(input) ? input : local__createLocal(input); + return +this === +input; + } else { + inputMs = +local__createLocal(input); + return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units)); + } + } + + function absFloor (number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); + } + } + + function diff (input, units, asFloat) { + var that = cloneWithOffset(input, this), + zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4, + delta, output; + + units = normalizeUnits(units); + + if (units === 'year' || units === 'month' || units === 'quarter') { + output = monthDiff(this, that); + if (units === 'quarter') { + output = output / 3; + } else if (units === 'year') { + output = output / 12; + } + } else { + delta = this - that; + output = units === 'second' ? delta / 1e3 : // 1000 + units === 'minute' ? delta / 6e4 : // 1000 * 60 + units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + delta; + } + return asFloat ? output : absFloor(output); + } + + function monthDiff (a, b) { + // difference in months + var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), + // b is in (anchor - 1 month, anchor + 1 month) + anchor = a.clone().add(wholeMonthDiff, 'months'), + anchor2, adjust; + + if (b - anchor < 0) { + anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor - anchor2); + } else { + anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor2 - anchor); + } + + return -(wholeMonthDiff + adjust); + } + + utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; + + function toString () { + return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); + } + + function moment_format__toISOString () { + var m = this.clone().utc(); + if (0 < m.year() && m.year() <= 9999) { + if ('function' === typeof Date.prototype.toISOString) { + // native implementation is ~50x faster, use it when we can + return this.toDate().toISOString(); + } else { + return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + } else { + return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + } + + function moment_format__format (inputString) { + var output = formatMoment(this, inputString || utils_hooks__hooks.defaultFormat); + return this.localeData().postformat(output); + } + + function from (time, withoutSuffix) { + if (!this.isValid()) { + return this.localeData().invalidDate(); + } + return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); + } + + function fromNow (withoutSuffix) { + return this.from(local__createLocal(), withoutSuffix); + } + + function to (time, withoutSuffix) { + if (!this.isValid()) { + return this.localeData().invalidDate(); + } + return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix); + } + + function toNow (withoutSuffix) { + return this.to(local__createLocal(), withoutSuffix); + } + + function locale (key) { + var newLocaleData; + + if (key === undefined) { + return this._locale._abbr; + } else { + newLocaleData = locale_locales__getLocale(key); + if (newLocaleData != null) { + this._locale = newLocaleData; + } + return this; + } + } + + var lang = deprecate( + 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', + function (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); + } + } + ); + + function localeData () { + return this._locale; + } + + function startOf (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 'quarter': + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoWeek': + 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); + } + + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } + if (units === 'isoWeek') { + this.isoWeekday(1); + } + + // quarters are also special + if (units === 'quarter') { + this.month(Math.floor(this.month() / 3) * 3); + } + + return this; + } + + function endOf (units) { + units = normalizeUnits(units); + if (units === undefined || units === 'millisecond') { + return this; + } + return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); + } + + function to_type__valueOf () { + return +this._d - ((this._offset || 0) * 60000); + } + + function unix () { + return Math.floor(+this / 1000); + } + + function toDate () { + return this._offset ? new Date(+this) : this._d; + } + + function toArray () { + var m = this; + return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()]; + } + + function moment_valid__isValid () { + return valid__isValid(this); + } + + function parsingFlags () { + return extend({}, getParsingFlags(this)); + } + + function invalidAt () { + return getParsingFlags(this).overflow; + } + + addFormatToken(0, ['gg', 2], 0, function () { + return this.weekYear() % 100; + }); + + addFormatToken(0, ['GG', 2], 0, function () { + return this.isoWeekYear() % 100; + }); + + function addWeekYearFormatToken (token, getter) { + addFormatToken(0, [token, token.length], 0, getter); + } + + addWeekYearFormatToken('gggg', 'weekYear'); + addWeekYearFormatToken('ggggg', 'weekYear'); + addWeekYearFormatToken('GGGG', 'isoWeekYear'); + addWeekYearFormatToken('GGGGG', 'isoWeekYear'); + + // ALIASES + + addUnitAlias('weekYear', 'gg'); + addUnitAlias('isoWeekYear', 'GG'); + + // PARSING + + addRegexToken('G', matchSigned); + addRegexToken('g', matchSigned); + addRegexToken('GG', match1to2, match2); + addRegexToken('gg', match1to2, match2); + addRegexToken('GGGG', match1to4, match4); + addRegexToken('gggg', match1to4, match4); + addRegexToken('GGGGG', match1to6, match6); + addRegexToken('ggggg', match1to6, match6); + + addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) { + week[token.substr(0, 2)] = toInt(input); + }); + + addWeekParseToken(['gg', 'GG'], function (input, week, config, token) { + week[token] = utils_hooks__hooks.parseTwoDigitYear(input); + }); + + // HELPERS + + function weeksInYear(year, dow, doy) { + return weekOfYear(local__createLocal([year, 11, 31 + dow - doy]), dow, doy).week; + } + + // MOMENTS + + function getSetWeekYear (input) { + var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year; + return input == null ? year : this.add((input - year), 'y'); + } + + function getSetISOWeekYear (input) { + var year = weekOfYear(this, 1, 4).year; + return input == null ? year : this.add((input - year), 'y'); + } + + function getISOWeeksInYear () { + return weeksInYear(this.year(), 1, 4); + } + + function getWeeksInYear () { + var weekInfo = this.localeData()._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); + } + + addFormatToken('Q', 0, 0, 'quarter'); + + // ALIASES + + addUnitAlias('quarter', 'Q'); + + // PARSING + + addRegexToken('Q', match1); + addParseToken('Q', function (input, array) { + array[MONTH] = (toInt(input) - 1) * 3; + }); + + // MOMENTS + + function getSetQuarter (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); + } + + addFormatToken('D', ['DD', 2], 'Do', 'date'); + + // ALIASES + + addUnitAlias('date', 'D'); + + // PARSING + + addRegexToken('D', match1to2); + addRegexToken('DD', match1to2, match2); + addRegexToken('Do', function (isStrict, locale) { + return isStrict ? locale._ordinalParse : locale._ordinalParseLenient; + }); + + addParseToken(['D', 'DD'], DATE); + addParseToken('Do', function (input, array) { + array[DATE] = toInt(input.match(match1to2)[0], 10); + }); + + // MOMENTS + + var getSetDayOfMonth = makeGetSet('Date', true); + + addFormatToken('d', 0, 'do', 'day'); + + addFormatToken('dd', 0, 0, function (format) { + return this.localeData().weekdaysMin(this, format); + }); + + addFormatToken('ddd', 0, 0, function (format) { + return this.localeData().weekdaysShort(this, format); + }); + + addFormatToken('dddd', 0, 0, function (format) { + return this.localeData().weekdays(this, format); + }); + + addFormatToken('e', 0, 0, 'weekday'); + addFormatToken('E', 0, 0, 'isoWeekday'); + + // ALIASES + + addUnitAlias('day', 'd'); + addUnitAlias('weekday', 'e'); + addUnitAlias('isoWeekday', 'E'); + + // PARSING + + addRegexToken('d', match1to2); + addRegexToken('e', match1to2); + addRegexToken('E', match1to2); + addRegexToken('dd', matchWord); + addRegexToken('ddd', matchWord); + addRegexToken('dddd', matchWord); + + addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config) { + var weekday = config._locale.weekdaysParse(input); + // if we didn't get a weekday name, mark the date as invalid + if (weekday != null) { + week.d = weekday; + } else { + getParsingFlags(config).invalidWeekday = input; + } + }); + + addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { + week[token] = toInt(input); + }); + + // HELPERS + + function parseWeekday(input, locale) { + if (typeof input === 'string') { + if (!isNaN(input)) { + input = parseInt(input, 10); + } + else { + input = locale.weekdaysParse(input); + if (typeof input !== 'number') { + return null; + } + } + } + return input; + } + + // LOCALES + + var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'); + function localeWeekdays (m) { + return this._weekdays[m.day()]; + } + + var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'); + function localeWeekdaysShort (m) { + return this._weekdaysShort[m.day()]; + } + + var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'); + function localeWeekdaysMin (m) { + return this._weekdaysMin[m.day()]; + } + + function localeWeekdaysParse (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 = local__createLocal([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; + } + } + } + + // MOMENTS + + function getSetDayOfWeek (input) { + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.localeData()); + return this.add(input - day, 'd'); + } else { + return day; + } + } + + function getSetLocaleDayOfWeek (input) { + var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; + return input == null ? weekday : this.add(input - weekday, 'd'); + } + + function getSetISODayOfWeek (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); + } + + addFormatToken('H', ['HH', 2], 0, 'hour'); + addFormatToken('h', ['hh', 2], 0, function () { + return this.hours() % 12 || 12; + }); + + function meridiem (token, lowercase) { + addFormatToken(token, 0, 0, function () { + return this.localeData().meridiem(this.hours(), this.minutes(), lowercase); + }); + } + + meridiem('a', true); + meridiem('A', false); + + // ALIASES + + addUnitAlias('hour', 'h'); + + // PARSING + + function matchMeridiem (isStrict, locale) { + return locale._meridiemParse; + } + + addRegexToken('a', matchMeridiem); + addRegexToken('A', matchMeridiem); + addRegexToken('H', match1to2); + addRegexToken('h', match1to2); + addRegexToken('HH', match1to2, match2); + addRegexToken('hh', match1to2, match2); + + addParseToken(['H', 'HH'], HOUR); + addParseToken(['a', 'A'], function (input, array, config) { + config._isPm = config._locale.isPM(input); + config._meridiem = input; + }); + addParseToken(['h', 'hh'], function (input, array, config) { + array[HOUR] = toInt(input); + getParsingFlags(config).bigHour = true; + }); + + // LOCALES + + function localeIsPM (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); + } + + var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; + function localeMeridiem (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + } + + + // MOMENTS + + // Setting the hour should keep the time, because the user explicitly + // specified which hour he wants. So trying to maintain the same hour (in + // a new timezone) makes sense. Adding/subtracting hours does not follow + // this rule. + var getSetHour = makeGetSet('Hours', true); + + addFormatToken('m', ['mm', 2], 0, 'minute'); + + // ALIASES + + addUnitAlias('minute', 'm'); + + // PARSING + + addRegexToken('m', match1to2); + addRegexToken('mm', match1to2, match2); + addParseToken(['m', 'mm'], MINUTE); + + // MOMENTS + + var getSetMinute = makeGetSet('Minutes', false); + + addFormatToken('s', ['ss', 2], 0, 'second'); + + // ALIASES + + addUnitAlias('second', 's'); + + // PARSING + + addRegexToken('s', match1to2); + addRegexToken('ss', match1to2, match2); + addParseToken(['s', 'ss'], SECOND); + + // MOMENTS + + var getSetSecond = makeGetSet('Seconds', false); + + addFormatToken('S', 0, 0, function () { + return ~~(this.millisecond() / 100); + }); + + addFormatToken(0, ['SS', 2], 0, function () { + return ~~(this.millisecond() / 10); + }); + + function millisecond__milliseconds (token) { + addFormatToken(0, [token, 3], 0, 'millisecond'); + } + + millisecond__milliseconds('SSS'); + millisecond__milliseconds('SSSS'); + + // ALIASES + + addUnitAlias('millisecond', 'ms'); + + // PARSING + + addRegexToken('S', match1to3, match1); + addRegexToken('SS', match1to3, match2); + addRegexToken('SSS', match1to3, match3); + addRegexToken('SSSS', matchUnsigned); + addParseToken(['S', 'SS', 'SSS', 'SSSS'], function (input, array) { + array[MILLISECOND] = toInt(('0.' + input) * 1000); + }); + + // MOMENTS + + var getSetMillisecond = makeGetSet('Milliseconds', false); + + addFormatToken('z', 0, 0, 'zoneAbbr'); + addFormatToken('zz', 0, 0, 'zoneName'); + + // MOMENTS + + function getZoneAbbr () { + return this._isUTC ? 'UTC' : ''; + } + + function getZoneName () { + return this._isUTC ? 'Coordinated Universal Time' : ''; + } + + var momentPrototype__proto = Moment.prototype; + + momentPrototype__proto.add = add_subtract__add; + momentPrototype__proto.calendar = moment_calendar__calendar; + momentPrototype__proto.clone = clone; + momentPrototype__proto.diff = diff; + momentPrototype__proto.endOf = endOf; + momentPrototype__proto.format = moment_format__format; + momentPrototype__proto.from = from; + momentPrototype__proto.fromNow = fromNow; + momentPrototype__proto.to = to; + momentPrototype__proto.toNow = toNow; + momentPrototype__proto.get = getSet; + momentPrototype__proto.invalidAt = invalidAt; + momentPrototype__proto.isAfter = isAfter; + momentPrototype__proto.isBefore = isBefore; + momentPrototype__proto.isBetween = isBetween; + momentPrototype__proto.isSame = isSame; + momentPrototype__proto.isValid = moment_valid__isValid; + momentPrototype__proto.lang = lang; + momentPrototype__proto.locale = locale; + momentPrototype__proto.localeData = localeData; + momentPrototype__proto.max = prototypeMax; + momentPrototype__proto.min = prototypeMin; + momentPrototype__proto.parsingFlags = parsingFlags; + momentPrototype__proto.set = getSet; + momentPrototype__proto.startOf = startOf; + momentPrototype__proto.subtract = add_subtract__subtract; + momentPrototype__proto.toArray = toArray; + momentPrototype__proto.toDate = toDate; + momentPrototype__proto.toISOString = moment_format__toISOString; + momentPrototype__proto.toJSON = moment_format__toISOString; + momentPrototype__proto.toString = toString; + momentPrototype__proto.unix = unix; + momentPrototype__proto.valueOf = to_type__valueOf; + + // Year + momentPrototype__proto.year = getSetYear; + momentPrototype__proto.isLeapYear = getIsLeapYear; + + // Week Year + momentPrototype__proto.weekYear = getSetWeekYear; + momentPrototype__proto.isoWeekYear = getSetISOWeekYear; + + // Quarter + momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter; + + // Month + momentPrototype__proto.month = getSetMonth; + momentPrototype__proto.daysInMonth = getDaysInMonth; + + // Week + momentPrototype__proto.week = momentPrototype__proto.weeks = getSetWeek; + momentPrototype__proto.isoWeek = momentPrototype__proto.isoWeeks = getSetISOWeek; + momentPrototype__proto.weeksInYear = getWeeksInYear; + momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear; + + // Day + momentPrototype__proto.date = getSetDayOfMonth; + momentPrototype__proto.day = momentPrototype__proto.days = getSetDayOfWeek; + momentPrototype__proto.weekday = getSetLocaleDayOfWeek; + momentPrototype__proto.isoWeekday = getSetISODayOfWeek; + momentPrototype__proto.dayOfYear = getSetDayOfYear; + + // Hour + momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour; + + // Minute + momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute; + + // Second + momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond; + + // Millisecond + momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond; + + // Offset + momentPrototype__proto.utcOffset = getSetOffset; + momentPrototype__proto.utc = setOffsetToUTC; + momentPrototype__proto.local = setOffsetToLocal; + momentPrototype__proto.parseZone = setOffsetToParsedOffset; + momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset; + momentPrototype__proto.isDST = isDaylightSavingTime; + momentPrototype__proto.isDSTShifted = isDaylightSavingTimeShifted; + momentPrototype__proto.isLocal = isLocal; + momentPrototype__proto.isUtcOffset = isUtcOffset; + momentPrototype__proto.isUtc = isUtc; + momentPrototype__proto.isUTC = isUtc; + + // Timezone + momentPrototype__proto.zoneAbbr = getZoneAbbr; + momentPrototype__proto.zoneName = getZoneName; + + // Deprecations + momentPrototype__proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); + momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); + momentPrototype__proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); + momentPrototype__proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone); + + var momentPrototype = momentPrototype__proto; + + function moment_moment__createUnix (input) { + return local__createLocal(input * 1000); + } + + function moment_moment__createInZone () { + return local__createLocal.apply(null, arguments).parseZone(); + } + + var defaultCalendar = { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }; + + function locale_calendar__calendar (key, mom, now) { + var output = this._calendar[key]; + return typeof output === 'function' ? output.call(mom, now) : output; + } + + var defaultLongDateFormat = { + LTS : 'h:mm:ss A', + LT : 'h:mm A', + L : 'MM/DD/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY LT', + LLLL : 'dddd, MMMM D, YYYY LT' + }; + + function longDateFormat (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; + } + + var defaultInvalidDate = 'Invalid date'; + + function invalidDate () { + return this._invalidDate; + } + + var defaultOrdinal = '%d'; + var defaultOrdinalParse = /\d{1,2}/; + + function ordinal (number) { + return this._ordinal.replace('%d', number); + } + + function preParsePostFormat (string) { + return string; + } + + var defaultRelativeTime = { + 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' + }; + + function relative__relativeTime (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (typeof output === 'function') ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + } + + function pastFuture (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); + } + + function locale_set__set (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (typeof prop === 'function') { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + // Lenient ordinal parsing accepts just a number in addition to + // number + (possibly) stuff coming from _ordinalParseLenient. + this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source); + } + + var prototype__proto = Locale.prototype; + + prototype__proto._calendar = defaultCalendar; + prototype__proto.calendar = locale_calendar__calendar; + prototype__proto._longDateFormat = defaultLongDateFormat; + prototype__proto.longDateFormat = longDateFormat; + prototype__proto._invalidDate = defaultInvalidDate; + prototype__proto.invalidDate = invalidDate; + prototype__proto._ordinal = defaultOrdinal; + prototype__proto.ordinal = ordinal; + prototype__proto._ordinalParse = defaultOrdinalParse; + prototype__proto.preparse = preParsePostFormat; + prototype__proto.postformat = preParsePostFormat; + prototype__proto._relativeTime = defaultRelativeTime; + prototype__proto.relativeTime = relative__relativeTime; + prototype__proto.pastFuture = pastFuture; + prototype__proto.set = locale_set__set; + + // Month + prototype__proto.months = localeMonths; + prototype__proto._months = defaultLocaleMonths; + prototype__proto.monthsShort = localeMonthsShort; + prototype__proto._monthsShort = defaultLocaleMonthsShort; + prototype__proto.monthsParse = localeMonthsParse; + + // Week + prototype__proto.week = localeWeek; + prototype__proto._week = defaultLocaleWeek; + prototype__proto.firstDayOfYear = localeFirstDayOfYear; + prototype__proto.firstDayOfWeek = localeFirstDayOfWeek; + + // Day of Week + prototype__proto.weekdays = localeWeekdays; + prototype__proto._weekdays = defaultLocaleWeekdays; + prototype__proto.weekdaysMin = localeWeekdaysMin; + prototype__proto._weekdaysMin = defaultLocaleWeekdaysMin; + prototype__proto.weekdaysShort = localeWeekdaysShort; + prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort; + prototype__proto.weekdaysParse = localeWeekdaysParse; + + // Hours + prototype__proto.isPM = localeIsPM; + prototype__proto._meridiemParse = defaultLocaleMeridiemParse; + prototype__proto.meridiem = localeMeridiem; + + function lists__get (format, index, field, setter) { + var locale = locale_locales__getLocale(); + var utc = create_utc__createUTC().set(setter, index); + return locale[field](utc, format); + } + + function list (format, index, field, count, setter) { + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + + if (index != null) { + return lists__get(format, index, field, setter); + } + + var i; + var out = []; + for (i = 0; i < count; i++) { + out[i] = lists__get(format, i, field, setter); + } + return out; + } + + function lists__listMonths (format, index) { + return list(format, index, 'months', 12, 'month'); + } + + function lists__listMonthsShort (format, index) { + return list(format, index, 'monthsShort', 12, 'month'); + } + + function lists__listWeekdays (format, index) { + return list(format, index, 'weekdays', 7, 'day'); + } + + function lists__listWeekdaysShort (format, index) { + return list(format, index, 'weekdaysShort', 7, 'day'); + } + + function lists__listWeekdaysMin (format, index) { + return list(format, index, 'weekdaysMin', 7, 'day'); + } + + locale_locales__getSetGlobalLocale('en', { + ordinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); + + // Side effect imports + utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale); + utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale); + + var mathAbs = Math.abs; + + function duration_abs__abs () { + var data = this._data; + + this._milliseconds = mathAbs(this._milliseconds); + this._days = mathAbs(this._days); + this._months = mathAbs(this._months); + + data.milliseconds = mathAbs(data.milliseconds); + data.seconds = mathAbs(data.seconds); + data.minutes = mathAbs(data.minutes); + data.hours = mathAbs(data.hours); + data.months = mathAbs(data.months); + data.years = mathAbs(data.years); + + return this; + } + + function duration_add_subtract__addSubtract (duration, input, value, direction) { + var other = create__createDuration(input, value); + + duration._milliseconds += direction * other._milliseconds; + duration._days += direction * other._days; + duration._months += direction * other._months; + + return duration._bubble(); + } + + // supports only 2.0-style add(1, 's') or add(duration) + function duration_add_subtract__add (input, value) { + return duration_add_subtract__addSubtract(this, input, value, 1); + } + + // supports only 2.0-style subtract(1, 's') or subtract(duration) + function duration_add_subtract__subtract (input, value) { + return duration_add_subtract__addSubtract(this, input, value, -1); + } + + function bubble () { + var milliseconds = this._milliseconds; + var days = this._days; + var months = this._months; + var data = this._data; + var seconds, minutes, hours, years = 0; + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absFloor(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absFloor(seconds / 60); + data.minutes = minutes % 60; + + hours = absFloor(minutes / 60); + data.hours = hours % 24; + + days += absFloor(hours / 24); + + // Accurately convert days to years, assume start from year 0. + years = absFloor(daysToYears(days)); + days -= absFloor(yearsToDays(years)); + + // 30 days to a month + // TODO (iskren): Use anchor date (like 1st Jan) to compute this. + months += absFloor(days / 30); + days %= 30; + + // 12 months -> 1 year + years += absFloor(months / 12); + months %= 12; + + data.days = days; + data.months = months; + data.years = years; + + return this; + } + + function daysToYears (days) { + // 400 years have 146097 days (taking into account leap year rules) + return days * 400 / 146097; + } + + function yearsToDays (years) { + // years * 365 + absFloor(years / 4) - + // absFloor(years / 100) + absFloor(years / 400); + return years * 146097 / 400; + } + + function as (units) { + var days; + var months; + var milliseconds = this._milliseconds; + + units = normalizeUnits(units); + + if (units === 'month' || units === 'year') { + days = this._days + milliseconds / 864e5; + months = this._months + daysToYears(days) * 12; + return units === 'month' ? months : months / 12; + } else { + // handle milliseconds separately because of floating point math errors (issue #1867) + days = this._days + Math.round(yearsToDays(this._months / 12)); + switch (units) { + case 'week' : return days / 7 + milliseconds / 6048e5; + case 'day' : return days + milliseconds / 864e5; + case 'hour' : return days * 24 + milliseconds / 36e5; + case 'minute' : return days * 1440 + milliseconds / 6e4; + case 'second' : return days * 86400 + milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 864e5) + milliseconds; + default: throw new Error('Unknown unit ' + units); + } + } + } + + // TODO: Use this.as('ms')? + function duration_as__valueOf () { + return ( + this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6 + ); + } + + function makeAs (alias) { + return function () { + return this.as(alias); + }; + } + + var asMilliseconds = makeAs('ms'); + var asSeconds = makeAs('s'); + var asMinutes = makeAs('m'); + var asHours = makeAs('h'); + var asDays = makeAs('d'); + var asWeeks = makeAs('w'); + var asMonths = makeAs('M'); + var asYears = makeAs('y'); + + function duration_get__get (units) { + units = normalizeUnits(units); + return this[units + 's'](); + } + + function makeGetter(name) { + return function () { + return this._data[name]; + }; + } + + var duration_get__milliseconds = makeGetter('milliseconds'); + var seconds = makeGetter('seconds'); + var minutes = makeGetter('minutes'); + var hours = makeGetter('hours'); + var days = makeGetter('days'); + var duration_get__months = makeGetter('months'); + var years = makeGetter('years'); + + function weeks () { + return absFloor(this.days() / 7); + } + + var round = Math.round; + var thresholds = { + s: 45, // seconds to minute + m: 45, // minutes to hour + h: 22, // hours to day + d: 26, // days to month + M: 11 // months to year + }; + + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { + return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); + } + + function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) { + var duration = create__createDuration(posNegDuration).abs(); + var seconds = round(duration.as('s')); + var minutes = round(duration.as('m')); + var hours = round(duration.as('h')); + var days = round(duration.as('d')); + var months = round(duration.as('M')); + var years = round(duration.as('y')); + + var a = seconds < thresholds.s && ['s', seconds] || + minutes === 1 && ['m'] || + minutes < thresholds.m && ['mm', minutes] || + hours === 1 && ['h'] || + hours < thresholds.h && ['hh', hours] || + days === 1 && ['d'] || + days < thresholds.d && ['dd', days] || + months === 1 && ['M'] || + months < thresholds.M && ['MM', months] || + years === 1 && ['y'] || ['yy', years]; + + a[2] = withoutSuffix; + a[3] = +posNegDuration > 0; + a[4] = locale; + return substituteTimeAgo.apply(null, a); + } + + // This function allows you to set a threshold for relative time strings + function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) { + if (thresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return thresholds[threshold]; + } + thresholds[threshold] = limit; + return true; + } + + function humanize (withSuffix) { + var locale = this.localeData(); + var output = duration_humanize__relativeTime(this, !withSuffix, locale); + + if (withSuffix) { + output = locale.pastFuture(+this, output); + } + + return locale.postformat(output); + } + + var iso_string__abs = Math.abs; + + function iso_string__toISOString() { + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var Y = iso_string__abs(this.years()); + var M = iso_string__abs(this.months()); + var D = iso_string__abs(this.days()); + var h = iso_string__abs(this.hours()); + var m = iso_string__abs(this.minutes()); + var s = iso_string__abs(this.seconds() + this.milliseconds() / 1000); + var total = this.asSeconds(); + + if (!total) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + + return (total < 0 ? '-' : '') + + 'P' + + (Y ? Y + 'Y' : '') + + (M ? M + 'M' : '') + + (D ? D + 'D' : '') + + ((h || m || s) ? 'T' : '') + + (h ? h + 'H' : '') + + (m ? m + 'M' : '') + + (s ? s + 'S' : ''); + } + + var duration_prototype__proto = Duration.prototype; + + duration_prototype__proto.abs = duration_abs__abs; + duration_prototype__proto.add = duration_add_subtract__add; + duration_prototype__proto.subtract = duration_add_subtract__subtract; + duration_prototype__proto.as = as; + duration_prototype__proto.asMilliseconds = asMilliseconds; + duration_prototype__proto.asSeconds = asSeconds; + duration_prototype__proto.asMinutes = asMinutes; + duration_prototype__proto.asHours = asHours; + duration_prototype__proto.asDays = asDays; + duration_prototype__proto.asWeeks = asWeeks; + duration_prototype__proto.asMonths = asMonths; + duration_prototype__proto.asYears = asYears; + duration_prototype__proto.valueOf = duration_as__valueOf; + duration_prototype__proto._bubble = bubble; + duration_prototype__proto.get = duration_get__get; + duration_prototype__proto.milliseconds = duration_get__milliseconds; + duration_prototype__proto.seconds = seconds; + duration_prototype__proto.minutes = minutes; + duration_prototype__proto.hours = hours; + duration_prototype__proto.days = days; + duration_prototype__proto.weeks = weeks; + duration_prototype__proto.months = duration_get__months; + duration_prototype__proto.years = years; + duration_prototype__proto.humanize = humanize; + duration_prototype__proto.toISOString = iso_string__toISOString; + duration_prototype__proto.toString = iso_string__toISOString; + duration_prototype__proto.toJSON = iso_string__toISOString; + duration_prototype__proto.locale = locale; + duration_prototype__proto.localeData = localeData; + + // Deprecations + duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString); + duration_prototype__proto.lang = lang; + + // Side effect imports + + addFormatToken('X', 0, 0, 'unix'); + addFormatToken('x', 0, 0, 'valueOf'); + + // PARSING + + addRegexToken('x', matchSigned); + addRegexToken('X', matchTimestamp); + addParseToken('X', function (input, array, config) { + config._d = new Date(parseFloat(input, 10) * 1000); + }); + addParseToken('x', function (input, array, config) { + config._d = new Date(toInt(input)); + }); + + // Side effect imports + + ; + + //! moment.js + //! version : 2.10.3 + //! authors : Tim Wood, Iskren Chernev, Moment.js contributors + //! license : MIT + //! momentjs.com + + utils_hooks__hooks.version = '2.10.3'; + + setHookCallback(local__createLocal); + + utils_hooks__hooks.fn = momentPrototype; + utils_hooks__hooks.min = min; + utils_hooks__hooks.max = max; + utils_hooks__hooks.utc = create_utc__createUTC; + utils_hooks__hooks.unix = moment_moment__createUnix; + utils_hooks__hooks.months = lists__listMonths; + utils_hooks__hooks.isDate = isDate; + utils_hooks__hooks.locale = locale_locales__getSetGlobalLocale; + utils_hooks__hooks.invalid = valid__createInvalid; + utils_hooks__hooks.duration = create__createDuration; + utils_hooks__hooks.isMoment = isMoment; + utils_hooks__hooks.weekdays = lists__listWeekdays; + utils_hooks__hooks.parseZone = moment_moment__createInZone; + utils_hooks__hooks.localeData = locale_locales__getLocale; + utils_hooks__hooks.isDuration = isDuration; + utils_hooks__hooks.monthsShort = lists__listMonthsShort; + utils_hooks__hooks.weekdaysMin = lists__listWeekdaysMin; + utils_hooks__hooks.defineLocale = defineLocale; + utils_hooks__hooks.weekdaysShort = lists__listWeekdaysShort; + utils_hooks__hooks.normalizeUnits = normalizeUnits; + utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold; + + var _moment__default = utils_hooks__hooks; + + //! moment.js locale configuration + //! locale : afrikaans (af) + //! author : Werner Mollentze : https://github.com/wernerm + + var af = _moment__default.defineLocale('af', { + months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'), + weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'), + weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'), + meridiemParse: /vm|nm/i, + isPM : function (input) { + return /^nm$/i.test(input); + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower ? 'vm' : 'VM'; + } else { + return isLower ? 'nm' : 'NM'; + } + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd, D MMMM YYYY LT' + }, + calendar : { + sameDay : '[Vandag om] LT', + nextDay : '[Môre om] LT', + nextWeek : 'dddd [om] LT', + lastDay : '[Gister om] LT', + lastWeek : '[Laas] dddd [om] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'oor %s', + past : '%s gelede', + s : '\'n paar sekondes', + m : '\'n minuut', + mm : '%d minute', + h : '\'n uur', + hh : '%d ure', + d : '\'n dag', + dd : '%d dae', + M : '\'n maand', + MM : '%d maande', + y : '\'n jaar', + yy : '%d jaar' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter + }, + week : { + dow : 1, // Maandag is die eerste dag van die week. + doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar. + } + }); + + //! moment.js locale configuration + //! locale : Moroccan Arabic (ar-ma) + //! author : ElFadili Yassine : https://github.com/ElFadiliY + //! author : Abdel Said : https://github.com/abdelsaid + + var ar_ma = _moment__default.defineLocale('ar-ma', { + months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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. + } + }); + + //! moment.js locale configuration + //! locale : Arabic Saudi Arabia (ar-sa) + //! author : Suhail Alkowaileet : https://github.com/xsoh + + var ar_sa__symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' + }, ar_sa__numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' + }; + + var ar_sa = _moment__default.defineLocale('ar-sa', { + months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D MMMM YYYY LT' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + 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 ar_sa__numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ar_sa__symbolMap[match]; + }).replace(/,/g, '،'); + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Tunisian Arabic (ar-tn) + + var ar_tn = _moment__default.defineLocale('ar-tn', { + months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat: { + LT: 'HH:mm', + LTS: 'LT:ss', + 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: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! Locale: Arabic (ar) + //! Author: Abdel Said: https://github.com/abdelsaid + //! Changes in months, weekdays: Ahmed Elkhatib + //! Native plural forms: forabi https://github.com/forabi + + var ar__symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' + }, ar__numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' + }, pluralForm = function (n) { + return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5; + }, plurals = { + s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'], + m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'], + h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'], + d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'], + M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'], + y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام'] + }, pluralize = function (u) { + return function (number, withoutSuffix, string, isFuture) { + var f = pluralForm(number), + str = plurals[u][pluralForm(number)]; + if (f === 2) { + str = str[withoutSuffix ? 0 : 1]; + } + return str.replace(/%d/i, number); + }; + }, ar__months = [ + 'كانون الثاني يناير', + 'شباط فبراير', + 'آذار مارس', + 'نيسان أبريل', + 'أيار مايو', + 'حزيران يونيو', + 'تموز يوليو', + 'آب أغسطس', + 'أيلول سبتمبر', + 'تشرين الأول أكتوبر', + 'تشرين الثاني نوفمبر', + 'كانون الأول ديسمبر' + ]; + + var ar = _moment__default.defineLocale('ar', { + months : ar__months, + monthsShort : ar__months, + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'D/\u200FM/\u200FYYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D MMMM YYYY LT' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + 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 : pluralize('s'), + m : pluralize('m'), + mm : pluralize('m'), + h : pluralize('h'), + hh : pluralize('h'), + d : pluralize('d'), + dd : pluralize('d'), + M : pluralize('M'), + MM : pluralize('M'), + y : pluralize('y'), + yy : pluralize('y') + }, + preparse: function (string) { + return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { + return ar__numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ar__symbolMap[match]; + }).replace(/,/g, '،'); + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : azerbaijani (az) + //! author : topchiyev : https://github.com/topchiyev + + var az__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 az = _moment__default.defineLocale('az', { + months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'), + monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'), + weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'), + weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'), + weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : '[sabah saat] LT', + nextWeek : '[gələn həftə] dddd [saat] LT', + lastDay : '[dünən] LT', + lastWeek : '[keçən həftə] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s sonra', + past : '%s əvvəl', + s : 'birneçə saniyyə', + m : 'bir dəqiqə', + mm : '%d dəqiqə', + h : 'bir saat', + hh : '%d saat', + d : 'bir gün', + dd : '%d gün', + M : 'bir ay', + MM : '%d ay', + y : 'bir il', + yy : '%d il' + }, + meridiemParse: /gecə|səhər|gündüz|axşam/, + isPM : function (input) { + return /^(gündüz|axşam)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'gecə'; + } else if (hour < 12) { + return 'səhər'; + } else if (hour < 17) { + return 'gündüz'; + } else { + return 'axşam'; + } + }, + ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/, + 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 + (az__suffixes[a] || az__suffixes[b] || az__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. + } + }); + + //! moment.js locale configuration + //! locale : belarusian (be) + //! author : Dmitry Demidov : https://github.com/demidov91 + //! author: Praleska: http://praleska.pro/ + //! Author : Menelion Elensúle : https://github.com/Oire + + function be__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 be__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін', + 'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін', + 'dd': 'дзень_дні_дзён', + 'MM': 'месяц_месяцы_месяцаў', + 'yy': 'год_гады_гадоў' + }; + if (key === 'm') { + return withoutSuffix ? 'хвіліна' : 'хвіліну'; + } + else if (key === 'h') { + return withoutSuffix ? 'гадзіна' : 'гадзіну'; + } + else { + return number + ' ' + be__plural(format[key], +number); + } + } + function be__monthsCaseReplace(m, format) { + var months = { + 'nominative': 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_'), + 'accusative': 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_') + }, + nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; + } + function be__weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'), + 'accusative': 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_') + }, + nounCase = (/\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/).test(format) ? + 'accusative' : + 'nominative'; + return weekdays[nounCase][m.day()]; + } + + var be = _moment__default.defineLocale('be', { + months : be__monthsCaseReplace, + monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'), + weekdays : be__weekdaysCaseReplace, + weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 '[У] dddd [ў] LT'; + }, + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return '[У мінулую] dddd [ў] LT'; + case 1: + case 2: + case 4: + return '[У мінулы] dddd [ў] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'праз %s', + past : '%s таму', + s : 'некалькі секунд', + m : be__relativeTimeWithPlural, + mm : be__relativeTimeWithPlural, + h : be__relativeTimeWithPlural, + hh : be__relativeTimeWithPlural, + d : 'дзень', + dd : be__relativeTimeWithPlural, + M : 'месяц', + MM : be__relativeTimeWithPlural, + y : 'год', + yy : be__relativeTimeWithPlural + }, + meridiemParse: /ночы|раніцы|дня|вечара/, + isPM : function (input) { + return /^(дня|вечара)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночы'; + } else if (hour < 12) { + return 'раніцы'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечара'; + } + }, + ordinalParse: /\d{1,2}-(і|ы|га)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : 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. + } + }); + + //! moment.js locale configuration + //! locale : bulgarian (bg) + //! author : Krasen Borisov : https://github.com/kraz + + var bg = _moment__default.defineLocale('bg', { + months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'), + weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + 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 години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Bengali (bn) + //! author : Kaushik Gandhi : https://github.com/kaushikgandhi + + var bn__symbolMap = { + '1': '১', + '2': '২', + '3': '৩', + '4': '৪', + '5': '৫', + '6': '৬', + '7': '৭', + '8': '৮', + '9': '৯', + '0': '০' + }, + bn__numberMap = { + '১': '1', + '২': '2', + '৩': '3', + '৪': '4', + '৫': '5', + '৬': '6', + '৭': '7', + '৮': '8', + '৯': '9', + '০': '0' + }; + + var bn = _moment__default.defineLocale('bn', { + months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'), + monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split('_'), + weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রুবার_শনিবার'.split('_'), + weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্রু_শনি'.split('_'), + weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'), + longDateFormat : { + LT : 'A h:mm সময়', + LTS : 'A h:mm:ss সময়', + 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 bn__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return bn__symbolMap[match]; + }); + }, + meridiemParse: /রাত|শকাল|দুপুর|বিকেল|রাত/, + isPM: function (input) { + return /^(দুপুর|বিকেল|রাত)$/.test(input); + }, + //Bengali is a vast language its spoken + //in different forms in various parts of the world. + //I have just generalized with most common one used + 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. + } + }); + + //! moment.js locale configuration + //! locale : tibetan (bo) + //! author : Thupten N. Chakrishar : https://github.com/vajradog + + var bo__symbolMap = { + '1': '༡', + '2': '༢', + '3': '༣', + '4': '༤', + '5': '༥', + '6': '༦', + '7': '༧', + '8': '༨', + '9': '༩', + '0': '༠' + }, + bo__numberMap = { + '༡': '1', + '༢': '2', + '༣': '3', + '༤': '4', + '༥': '5', + '༦': '6', + '༧': '7', + '༨': '8', + '༩': '9', + '༠': '0' + }; + + var bo = _moment__default.defineLocale('bo', { + months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'), + weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + longDateFormat : { + LT : 'A h:mm', + LTS : 'LT:ss', + 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 : '[བདུན་ཕྲག་རྗེས་མ], 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 bo__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return bo__symbolMap[match]; + }); + }, + meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/, + isPM: function (input) { + return /^(ཉིན་གུང|དགོང་དག|མཚན་མོ)$/.test(input); + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : 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); + } + + var br = _moment__default.defineLocale('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', + LTS : 'h[e]mm:ss 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 + }, + ordinalParse: /\d{1,2}(añ|vet)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : bosnian (bs) + //! author : Nedim Cholich : https://github.com/frontyard + //! based on (hr) translation by Bojan Marković + + function bs__translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } + } + + var bs = _moment__default.defineLocale('bs', { + months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'), + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : bs__translate, + mm : bs__translate, + h : bs__translate, + hh : bs__translate, + d : 'dan', + dd : bs__translate, + M : 'mjesec', + MM : bs__translate, + y : 'godinu', + yy : bs__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : catalan (ca) + //! author : Juan G. Hurtado : https://github.com/juanghurtado + + var ca = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(r|n|t|è|a)/, + ordinal : function (number, period) { + var output = (number === 1) ? 'r' : + (number === 2) ? 'n' : + (number === 3) ? 'r' : + (number === 4) ? 't' : 'è'; + if (period === 'w' || period === 'W') { + output = 'a'; + } + 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. + } + }); + + //! moment.js locale configuration + //! locale : czech (cs) + //! author : petrbela : https://github.com/petrbela + + var cs__months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'), + cs__monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_'); + function cs__plural(n) { + return (n > 1) && (n < 5) && (~~(n / 10) !== 1); + } + function cs__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 sekund' : 'pár sekundami'; + 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 + (cs__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 + (cs__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 + (cs__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 + (cs__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 + (cs__plural(number) ? 'roky' : 'let'); + } else { + return result + 'lety'; + } + break; + } + } + + var cs = _moment__default.defineLocale('cs', { + months : cs__months, + monthsShort : cs__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; + }(cs__months, cs__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', + LTS : 'LT:ss', + 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 : cs__translate, + m : cs__translate, + mm : cs__translate, + h : cs__translate, + hh : cs__translate, + d : cs__translate, + dd : cs__translate, + M : cs__translate, + MM : cs__translate, + y : cs__translate, + yy : cs__translate + }, + ordinalParse : /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : chuvash (cv) + //! author : Anatoly Mironov : https://github.com/mirontoli + + var cv = _moment__default.defineLocale('cv', { + months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'), + monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'), + weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'), + weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'), + weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 ҫул' + }, + ordinalParse: /\d{1,2}-мӗш/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Welsh (cy) + //! author : Robert Allen + + var cy = _moment__default.defineLocale('cy', { + months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'), + monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'), + weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'), + weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'), + weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'), + // time formats are the same as en-gb + longDateFormat: { + LT: 'HH:mm', + LTS : 'LT:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY LT', + LLLL: 'dddd, D MMMM YYYY LT' + }, + calendar: { + sameDay: '[Heddiw am] LT', + nextDay: '[Yfory am] LT', + nextWeek: 'dddd [am] LT', + lastDay: '[Ddoe am] LT', + lastWeek: 'dddd [diwethaf am] LT', + sameElse: 'L' + }, + relativeTime: { + future: 'mewn %s', + past: '%s yn ôl', + s: 'ychydig eiliadau', + m: 'munud', + mm: '%d munud', + h: 'awr', + hh: '%d awr', + d: 'diwrnod', + dd: '%d diwrnod', + M: 'mis', + MM: '%d mis', + y: 'blwyddyn', + yy: '%d flynedd' + }, + ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/, + // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh + ordinal: function (number) { + var b = number, + output = '', + lookup = [ + '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed + 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed + ]; + if (b > 20) { + if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) { + output = 'fed'; // not 30ain, 70ain or 90ain + } else { + output = 'ain'; + } + } else if (b > 0) { + output = lookup[b]; + } + 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. + } + }); + + //! moment.js locale configuration + //! locale : danish (da) + //! author : Ulrik Nielsen : https://github.com/mrbase + + var da = _moment__default.defineLocale('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', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd [d.] 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' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : austrian german (de-at) + //! author : lluchs : https://github.com/lluchs + //! author: Menelion Elensúle: https://github.com/Oire + //! author : Martin Groller : https://github.com/MadMG + + function de_at__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]; + } + + var de_at = _moment__default.defineLocale('de-at', { + months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort : 'Jän._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: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay: '[Heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[Morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[Gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + relativeTime : { + future : 'in %s', + past : 'vor %s', + s : 'ein paar Sekunden', + m : de_at__processRelativeTime, + mm : '%d Minuten', + h : de_at__processRelativeTime, + hh : '%d Stunden', + d : de_at__processRelativeTime, + dd : de_at__processRelativeTime, + M : de_at__processRelativeTime, + MM : de_at__processRelativeTime, + y : de_at__processRelativeTime, + yy : de_at__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : german (de) + //! author : lluchs : https://github.com/lluchs + //! author: Menelion Elensúle: https://github.com/Oire + + function de__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]; + } + + var de = _moment__default.defineLocale('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: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay: '[Heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[Morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[Gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + relativeTime : { + future : 'in %s', + past : 'vor %s', + s : 'ein paar Sekunden', + m : de__processRelativeTime, + mm : '%d Minuten', + h : de__processRelativeTime, + hh : '%d Stunden', + d : de__processRelativeTime, + dd : de__processRelativeTime, + M : de__processRelativeTime, + MM : de__processRelativeTime, + y : de__processRelativeTime, + yy : de__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : modern greek (el) + //! author : Aggelos Karalias : https://github.com/mehiel + + var el = _moment__default.defineLocale('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 ? 'πμ' : 'ΠΜ'; + } + }, + isPM : function (input) { + return ((input + '').toLowerCase()[0] === 'μ'); + }, + meridiemParse : /[ΠΜ]\.?Μ?\.?/i, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss 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 : function () { + switch (this.day()) { + case 6: + return '[το προηγούμενο] dddd [{}] LT'; + default: + return '[την προηγούμενη] dddd [{}] LT'; + } + }, + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendarEl[key], + hours = mom && mom.hours(); + if (typeof output === 'function') { + output = output.apply(mom); + } + 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 χρόνια' + }, + ordinalParse: /\d{1,2}η/, + ordinal: '%dη', + 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. + } + }); + + //! moment.js locale configuration + //! locale : australian english (en-au) + + var en_au = _moment__default.defineLocale('en-au', { + 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', + LTS : 'h:mm:ss 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' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : canadian english (en-ca) + //! author : Jonathan Abourbih : https://github.com/jonbca + + var en_ca = _moment__default.defineLocale('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', + LTS : 'h:mm:ss 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' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + 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; + } + }); + + //! moment.js locale configuration + //! locale : great britain english (en-gb) + //! author : Chris Gedrim : https://github.com/chrisgedrim + + var en_gb = _moment__default.defineLocale('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', + LTS : 'HH:mm:ss', + 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' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : 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! + + var eo = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + meridiemParse: /[ap]\.t\.m/i, + isPM: function (input) { + return input.charAt(0).toLowerCase() === 'p'; + }, + 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' + }, + ordinalParse: /\d{1,2}a/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : spanish (es) + //! author : Julio Napurí : https://github.com/julionc + + var monthsShortDot = 'Ene._Feb._Mar._Abr._May._Jun._Jul._Ago._Sep._Oct._Nov._Dic.'.split('_'), + es__monthsShort = 'Ene_Feb_Mar_Abr_May_Jun_Jul_Ago_Sep_Oct_Nov_Dic'.split('_'); + + var es = _moment__default.defineLocale('es', { + months : 'Enero_Febrero_Marzo_Abril_Mayo_Junio_Julio_Agosto_Septiembre_Octubre_Noviembre_Diciembre'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return es__monthsShort[m.month()]; + } else { + return monthsShortDot[m.month()]; + } + }, + 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', + LTS : 'LT:ss', + 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' + }, + ordinalParse : /\d{1,2}º/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : estonian (et) + //! author : Henry Kehlmann : https://github.com/madhenry + //! improvements : Illimar Tambek : https://github.com/ragulka + + function et__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'], + 'm' : ['ühe minuti', 'üks minut'], + 'mm': [number + ' minuti', number + ' minutit'], + 'h' : ['ühe tunni', 'tund aega', 'üks tund'], + 'hh': [number + ' tunni', number + ' tundi'], + 'd' : ['ühe päeva', 'üks päev'], + 'M' : ['kuu aja', 'kuu aega', 'üks kuu'], + 'MM': [number + ' kuu', number + ' kuud'], + 'y' : ['ühe aasta', 'aasta', 'üks aasta'], + 'yy': [number + ' aasta', number + ' aastat'] + }; + if (withoutSuffix) { + return format[key][2] ? format[key][2] : format[key][1]; + } + return isFuture ? format[key][0] : format[key][1]; + } + + var et = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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 : et__processRelativeTime, + m : et__processRelativeTime, + mm : et__processRelativeTime, + h : et__processRelativeTime, + hh : et__processRelativeTime, + d : et__processRelativeTime, + dd : '%d päeva', + M : et__processRelativeTime, + MM : et__processRelativeTime, + y : et__processRelativeTime, + yy : et__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : euskara (eu) + //! author : Eneko Illarramendi : https://github.com/eillarra + + var eu = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Persian (fa) + //! author : Ebrahim Byagowi : https://github.com/ebraminio + + var fa__symbolMap = { + '1': '۱', + '2': '۲', + '3': '۳', + '4': '۴', + '5': '۵', + '6': '۶', + '7': '۷', + '8': '۸', + '9': '۹', + '0': '۰' + }, fa__numberMap = { + '۱': '1', + '۲': '2', + '۳': '3', + '۴': '4', + '۵': '5', + '۶': '6', + '۷': '7', + '۸': '8', + '۹': '9', + '۰': '0' + }; + + var fa = _moment__default.defineLocale('fa', { + months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd, D MMMM YYYY LT' + }, + meridiemParse: /قبل از ظهر|بعد از ظهر/, + isPM: function (input) { + return /بعد از ظهر/.test(input); + }, + 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 fa__numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return fa__symbolMap[match]; + }).replace(/,/g, '،'); + }, + ordinalParse: /\d{1,2}م/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : finnish (fi) + //! author : Tarmo Aidantausta : https://github.com/bleadof + + var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '), + numbersFuture = [ + 'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden', + numbersPast[7], numbersPast[8], numbersPast[9] + ]; + function fi__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 = verbalNumber(number, isFuture) + ' ' + result; + return result; + } + function verbalNumber(number, isFuture) { + return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number; + } + + var fi = _moment__default.defineLocale('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', + LTS : 'HH.mm.ss', + 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 : fi__translate, + m : fi__translate, + mm : fi__translate, + h : fi__translate, + hh : fi__translate, + d : fi__translate, + dd : fi__translate, + M : fi__translate, + MM : fi__translate, + y : fi__translate, + yy : fi__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : faroese (fo) + //! author : Ragnar Johannesen : https://github.com/ragnar123 + + var fo = _moment__default.defineLocale('fo', { + months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), + weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'), + weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'), + weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D. MMMM, YYYY LT' + }, + calendar : { + sameDay : '[Í dag kl.] LT', + nextDay : '[Í morgin kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[Í gjár kl.] LT', + lastWeek : '[síðstu] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'um %s', + past : '%s síðani', + s : 'fá sekund', + m : 'ein minutt', + mm : '%d minuttir', + h : 'ein tími', + hh : '%d tímar', + d : 'ein dagur', + dd : '%d dagar', + M : 'ein mánaði', + MM : '%d mánaðir', + y : 'eitt ár', + yy : '%d ár' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : canadian french (fr-ca) + //! author : Jonathan Abourbih : https://github.com/jonbca + + var fr_ca = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(er|)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : ''); + } + }); + + //! moment.js locale configuration + //! locale : french (fr) + //! author : John Fischer : https://github.com/jfroffice + + var fr = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(er|)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : frisian (fy) + //! author : Robin van der Vliet : https://github.com/robin0van0der0v + + var fy__monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_'), + fy__monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'); + + var fy = _moment__default.defineLocale('fy', { + months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return fy__monthsShortWithoutDots[m.month()]; + } else { + return fy__monthsShortWithDots[m.month()]; + } + }, + weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'), + weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'), + weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D MMMM YYYY LT' + }, + calendar : { + sameDay: '[hjoed om] LT', + nextDay: '[moarn om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[juster om] LT', + lastWeek: '[ôfrûne] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'oer %s', + past : '%s lyn', + s : 'in pear sekonden', + m : 'ien minút', + mm : '%d minuten', + h : 'ien oere', + hh : '%d oeren', + d : 'ien dei', + dd : '%d dagen', + M : 'ien moanne', + MM : '%d moannen', + y : 'ien jier', + yy : '%d jierren' + }, + ordinalParse: /\d{1,2}(ste|de)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : galician (gl) + //! author : Juan G. Hurtado : https://github.com/juanghurtado + + var gl = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse : /\d{1,2}º/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Hebrew (he) + //! author : Tomer Cohen : https://github.com/tomer + //! author : Moshe Simantov : https://github.com/DevelopmentIL + //! author : Tal Ater : https://github.com/TalAter + + var he = _moment__default.defineLocale('he', { + months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'), + monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'), + weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'), + weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'), + weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : function (number) { + if (number === 2) { + return 'שעתיים'; + } + return number + ' שעות'; + }, + d : 'יום', + dd : function (number) { + if (number === 2) { + return 'יומיים'; + } + return number + ' ימים'; + }, + M : 'חודש', + MM : function (number) { + if (number === 2) { + return 'חודשיים'; + } + return number + ' חודשים'; + }, + y : 'שנה', + yy : function (number) { + if (number === 2) { + return 'שנתיים'; + } else if (number % 10 === 0 && number !== 10) { + return number + ' שנה'; + } + return number + ' שנים'; + } + } + }); + + //! moment.js locale configuration + //! locale : hindi (hi) + //! author : Mayank Singhal : https://github.com/mayanksinghal + + var hi__symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + hi__numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var hi = _moment__default.defineLocale('hi', { + months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'), + monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'), + weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm बजे', + LTS : 'A h:mm:ss बजे', + 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 hi__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return hi__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. + meridiemParse: /रात|सुबह|दोपहर|शाम/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सुबह') { + return hour; + } else if (meridiem === 'दोपहर') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'शाम') { + return hour + 12; + } + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : hrvatski (hr) + //! author : Bojan Marković : https://github.com/bmarkovic + + function hr__translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } + } + + var hr = _moment__default.defineLocale('hr', { + months : 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_'), + monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'), + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : hr__translate, + mm : hr__translate, + h : hr__translate, + hh : hr__translate, + d : 'dan', + dd : hr__translate, + M : 'mjesec', + MM : hr__translate, + y : 'godinu', + yy : hr__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : 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 hu__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]'; + } + + var hu = _moment__default.defineLocale('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 : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'), + weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + L : 'YYYY.MM.DD.', + LL : 'YYYY. MMMM D.', + LLL : 'YYYY. MMMM D., LT', + LLLL : 'YYYY. MMMM D., dddd LT' + }, + meridiemParse: /de|du/i, + isPM: function (input) { + return input.charAt(1).toLowerCase() === 'u'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower === true ? 'de' : 'DE'; + } else { + return isLower === true ? 'du' : 'DU'; + } + }, + 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 : hu__translate, + m : hu__translate, + mm : hu__translate, + h : hu__translate, + hh : hu__translate, + d : hu__translate, + dd : hu__translate, + M : hu__translate, + MM : hu__translate, + y : hu__translate, + yy : hu__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Armenian (hy-am) + //! author : Armendarabyan : https://github.com/armendarabyan + + function hy_am__monthsCaseReplace(m, format) { + var months = { + 'nominative': 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_'), + 'accusative': 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_') + }, + nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; + } + function hy_am__monthsShortCaseReplace(m, format) { + var monthsShort = 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'); + return monthsShort[m.month()]; + } + function hy_am__weekdaysCaseReplace(m, format) { + var weekdays = 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'); + return weekdays[m.day()]; + } + + var hy_am = _moment__default.defineLocale('hy-am', { + months : hy_am__monthsCaseReplace, + monthsShort : hy_am__monthsShortCaseReplace, + weekdays : hy_am__weekdaysCaseReplace, + weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 'dddd [օրը ժամը] LT'; + }, + lastWeek: function () { + 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 տարի' + }, + meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/, + isPM: function (input) { + return /^(ցերեկվա|երեկոյան)$/.test(input); + }, + meridiem : function (hour) { + if (hour < 4) { + return 'գիշերվա'; + } else if (hour < 12) { + return 'առավոտվա'; + } else if (hour < 17) { + return 'ցերեկվա'; + } else { + return 'երեկոյան'; + } + }, + ordinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/, + ordinal: function (number, period) { + switch (period) { + case 'DDD': + case 'w': + case 'W': + case 'DDDo': + if (number === 1) { + return number + '-ին'; + } + 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. + } + }); + + //! moment.js locale configuration + //! locale : Bahasa Indonesia (id) + //! author : Mohammad Satrio Utomo : https://github.com/tyok + //! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan + + var id = _moment__default.defineLocale('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', + LTS : 'LT.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] LT', + LLLL : 'dddd, D MMMM YYYY [pukul] LT' + }, + meridiemParse: /pagi|siang|sore|malam/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'siang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sore' || meridiem === 'malam') { + return hour + 12; + } + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : icelandic (is) + //! author : Hinrik Örn Sigurðsson : https://github.com/hinrik + + function is__plural(n) { + if (n % 100 === 11) { + return true; + } else if (n % 10 === 1) { + return false; + } + return true; + } + function is__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 (is__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 (is__plural(number)) { + return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum'); + } + return result + 'klukkustund'; + case 'd': + if (withoutSuffix) { + return 'dagur'; + } + return isFuture ? 'dag' : 'degi'; + case 'dd': + if (is__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 (is__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 (is__plural(number)) { + return result + (withoutSuffix || isFuture ? 'ár' : 'árum'); + } + return result + (withoutSuffix || isFuture ? 'ár' : 'ári'); + } + } + + var is = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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 : is__translate, + m : is__translate, + mm : is__translate, + h : 'klukkustund', + hh : is__translate, + d : is__translate, + dd : is__translate, + M : is__translate, + MM : is__translate, + y : is__translate, + yy : is__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : italian (it) + //! author : Lorenzo : https://github.com/aliem + //! author: Mattia Larentis: https://github.com/nostalgiaz + + var it = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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: function () { + switch (this.day()) { + case 0: + return '[la scorsa] dddd [alle] LT'; + default: + return '[lo scorso] dddd [alle] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : function (s) { + return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s; + }, + past : '%s fa', + s : 'alcuni 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' + }, + ordinalParse : /\d{1,2}º/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : japanese (ja) + //! author : LI Long : https://github.com/baryon + + var ja = _moment__default.defineLocale('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分', + LTS : 'LTs秒', + L : 'YYYY/MM/DD', + LL : 'YYYY年M月D日', + LLL : 'YYYY年M月D日LT', + LLLL : 'YYYY年M月D日LT dddd' + }, + meridiemParse: /午前|午後/i, + isPM : function (input) { + return input === '午後'; + }, + 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年' + } + }); + + //! moment.js locale configuration + //! locale : Boso Jowo (jv) + //! author : Rony Lantip : https://github.com/lantip + //! reference: http://jv.wikipedia.org/wiki/Basa_Jawa + + var jv = _moment__default.defineLocale('jv', { + months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'), + weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'), + weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'), + weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'LT.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] LT', + LLLL : 'dddd, D MMMM YYYY [pukul] LT' + }, + meridiemParse: /enjing|siyang|sonten|ndalu/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'enjing') { + return hour; + } else if (meridiem === 'siyang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sonten' || meridiem === 'ndalu') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'enjing'; + } else if (hours < 15) { + return 'siyang'; + } else if (hours < 19) { + return 'sonten'; + } else { + return 'ndalu'; + } + }, + calendar : { + sameDay : '[Dinten puniko pukul] LT', + nextDay : '[Mbenjang pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kala wingi pukul] LT', + lastWeek : 'dddd [kepengker pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'wonten ing %s', + past : '%s ingkang kepengker', + s : 'sawetawis detik', + m : 'setunggal menit', + mm : '%d menit', + h : 'setunggal jam', + hh : '%d jam', + d : 'sedinten', + dd : '%d dinten', + M : 'sewulan', + MM : '%d wulan', + y : 'setaun', + yy : '%d taun' + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Georgian (ka) + //! author : Irakli Janiashvili : https://github.com/irakli-janiashvili + + function ka__monthsCaseReplace(m, format) { + var months = { + 'nominative': 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'), + 'accusative': 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_') + }, + nounCase = (/D[oD] *MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; + } + function ka__weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'), + 'accusative': 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_') + }, + nounCase = (/(წინა|შემდეგ)/).test(format) ? + 'accusative' : + 'nominative'; + return weekdays[nounCase][m.day()]; + } + + var ka = _moment__default.defineLocale('ka', { + months : ka__monthsCaseReplace, + monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'), + weekdays : ka__weekdaysCaseReplace, + weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'), + weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss 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 წელი' + }, + ordinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/, + 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 + } + }); + + //! moment.js locale configuration + //! locale : khmer (km) + //! author : Kruy Vanna : https://github.com/kruyvanna + + var km = _moment__default.defineLocale('km', { + months: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + monthsShort: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + longDateFormat: { + LT: 'HH:mm', + LTS : 'LT:ss', + 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: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : korean (ko) + //! + //! authors + //! + //! - Kyungwook, Park : https://github.com/kyungw00k + //! - Jeeeyul Lee <jeeeyul@gmail.com> + + var ko = _moment__default.defineLocale('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시 m분', + LTS : 'A h시 m분 s초', + L : 'YYYY.MM.DD', + LL : 'YYYY년 MMMM D일', + LLL : 'YYYY년 MMMM D일 LT', + LLLL : 'YYYY년 MMMM D일 dddd LT' + }, + 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년' + }, + ordinalParse : /\d{1,2}일/, + ordinal : '%d일', + meridiemParse : /오전|오후/, + isPM : function (token) { + return token === '오후'; + }, + meridiem : function (hour, minute, isUpper) { + return hour < 12 ? '오전' : '오후'; + } + }); + + //! moment.js locale configuration + //! locale : Luxembourgish (lb) + //! author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz + + function lb__processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eng Minutt', 'enger Minutt'], + 'h': ['eng Stonn', 'enger Stonn'], + 'd': ['een Dag', 'engem Dag'], + 'M': ['ee Mount', 'engem Mount'], + 'y': ['ee Joer', 'engem Joer'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; + } + function processFutureTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'a ' + string; + } + return 'an ' + string; + } + function processPastTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'viru ' + string; + } + return 'virun ' + string; + } + /** + * Returns true if the word before the given number loses the '-n' ending. + * e.g. 'an 10 Deeg' but 'a 5 Deeg' + * + * @param number {integer} + * @returns {boolean} + */ + function eifelerRegelAppliesToNumber(number) { + number = parseInt(number, 10); + if (isNaN(number)) { + return false; + } + if (number < 0) { + // Negative Number --> always true + return true; + } else if (number < 10) { + // Only 1 digit + if (4 <= number && number <= 7) { + return true; + } + return false; + } else if (number < 100) { + // 2 digits + var lastDigit = number % 10, firstDigit = number / 10; + if (lastDigit === 0) { + return eifelerRegelAppliesToNumber(firstDigit); + } + return eifelerRegelAppliesToNumber(lastDigit); + } else if (number < 10000) { + // 3 or 4 digits --> recursively check first digit + while (number >= 10) { + number = number / 10; + } + return eifelerRegelAppliesToNumber(number); + } else { + // Anything larger than 4 digits: recursively check first n-3 digits + number = number / 1000; + return eifelerRegelAppliesToNumber(number); + } + } + + var lb = _moment__default.defineLocale('lb', { + months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'), + weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'), + weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'), + longDateFormat: { + LT: 'H:mm [Auer]', + LTS: 'H:mm:ss [Auer]', + L: 'DD.MM.YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY LT', + LLLL: 'dddd, D. MMMM YYYY LT' + }, + calendar: { + sameDay: '[Haut um] LT', + sameElse: 'L', + nextDay: '[Muer um] LT', + nextWeek: 'dddd [um] LT', + lastDay: '[Gëschter um] LT', + lastWeek: function () { + // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule + switch (this.day()) { + case 2: + case 4: + return '[Leschten] dddd [um] LT'; + default: + return '[Leschte] dddd [um] LT'; + } + } + }, + relativeTime : { + future : processFutureTime, + past : processPastTime, + s : 'e puer Sekonnen', + m : lb__processRelativeTime, + mm : '%d Minutten', + h : lb__processRelativeTime, + hh : '%d Stonnen', + d : lb__processRelativeTime, + dd : '%d Deeg', + M : lb__processRelativeTime, + MM : '%d Méint', + y : lb__processRelativeTime, + yy : '%d Joer' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Lithuanian (lt) + //! author : Mindaugas Mozūras : https://github.com/mmozuras + + var lt__units = { + 'm' : 'minutė_minutės_minutę', + 'mm': 'minutės_minučių_minutes', + 'h' : 'valanda_valandos_valandą', + 'hh': 'valandos_valandų_valandas', + 'd' : 'diena_dienos_dieną', + 'dd': 'dienos_dienų_dienas', + 'M' : 'mėnuo_mėnesio_mėnesį', + 'MM': 'mėnesiai_mėnesių_mėnesius', + 'y' : 'metai_metų_metus', + 'yy': 'metai_metų_metus' + }, + weekDays = 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'); + function translateSeconds(number, withoutSuffix, key, isFuture) { + if (withoutSuffix) { + return 'kelios sekundės'; + } else { + return isFuture ? 'kelių sekundžių' : 'kelias sekundes'; + } + } + function translateSingular(number, withoutSuffix, key, isFuture) { + return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]); + } + function special(number) { + return number % 10 === 0 || (number > 10 && number < 20); + } + function forms(key) { + return lt__units[key].split('_'); + } + function lt__translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + if (number === 1) { + return result + translateSingular(number, withoutSuffix, key[0], isFuture); + } else if (withoutSuffix) { + return result + (special(number) ? forms(key)[1] : forms(key)[0]); + } else { + if (isFuture) { + return result + forms(key)[1]; + } else { + return result + (special(number) ? forms(key)[1] : forms(key)[2]); + } + } + } + function relativeWeekDay(moment, format) { + var nominative = format.indexOf('dddd HH:mm') === -1, + weekDay = weekDays[moment.day()]; + return nominative ? weekDay : weekDay.substring(0, weekDay.length - 2) + 'į'; + } + + var lt = _moment__default.defineLocale('lt', { + months : 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'), + monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'), + weekdays : relativeWeekDay, + weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'), + weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'YYYY-MM-DD', + LL : 'YYYY [m.] MMMM D [d.]', + LLL : 'YYYY [m.] MMMM D [d.], LT [val.]', + LLLL : 'YYYY [m.] MMMM D [d.], dddd, LT [val.]', + l : 'YYYY-MM-DD', + ll : 'YYYY [m.] MMMM D [d.]', + lll : 'YYYY [m.] MMMM D [d.], LT [val.]', + llll : 'YYYY [m.] MMMM D [d.], ddd, LT [val.]' + }, + calendar : { + sameDay : '[Šiandien] LT', + nextDay : '[Rytoj] LT', + nextWeek : 'dddd LT', + lastDay : '[Vakar] LT', + lastWeek : '[Praėjusį] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : 'po %s', + past : 'prieš %s', + s : translateSeconds, + m : translateSingular, + mm : lt__translate, + h : translateSingular, + hh : lt__translate, + d : translateSingular, + dd : lt__translate, + M : translateSingular, + MM : lt__translate, + y : translateSingular, + yy : lt__translate + }, + ordinalParse: /\d{1,2}-oji/, + ordinal : function (number) { + return number + '-oji'; + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : latvian (lv) + //! author : Kristaps Karlsons : https://github.com/skakri + //! author : Jānis Elmeris : https://github.com/JanisE + + var lv__units = { + 'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'h': 'stundas_stundām_stunda_stundas'.split('_'), + 'hh': 'stundas_stundām_stunda_stundas'.split('_'), + 'd': 'dienas_dienām_diena_dienas'.split('_'), + 'dd': 'dienas_dienām_diena_dienas'.split('_'), + 'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'y': 'gada_gadiem_gads_gadi'.split('_'), + 'yy': 'gada_gadiem_gads_gadi'.split('_') + }; + /** + * @param withoutSuffix boolean true = a length of time; false = before/after a period of time. + */ + function lv__format(forms, number, withoutSuffix) { + if (withoutSuffix) { + // E.g. "21 minūte", "3 minūtes". + return number % 10 === 1 && number !== 11 ? forms[2] : forms[3]; + } else { + // E.g. "21 minūtes" as in "pēc 21 minūtes". + // E.g. "3 minūtēm" as in "pēc 3 minūtēm". + return number % 10 === 1 && number !== 11 ? forms[0] : forms[1]; + } + } + function lv__relativeTimeWithPlural(number, withoutSuffix, key) { + return number + ' ' + lv__format(lv__units[key], number, withoutSuffix); + } + function relativeTimeWithSingular(number, withoutSuffix, key) { + return lv__format(lv__units[key], number, withoutSuffix); + } + function relativeSeconds(number, withoutSuffix) { + return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm'; + } + + var lv = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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 : 'pēc %s', + past : 'pirms %s', + s : relativeSeconds, + m : relativeTimeWithSingular, + mm : lv__relativeTimeWithPlural, + h : relativeTimeWithSingular, + hh : lv__relativeTimeWithPlural, + d : relativeTimeWithSingular, + dd : lv__relativeTimeWithPlural, + M : relativeTimeWithSingular, + MM : lv__relativeTimeWithPlural, + y : relativeTimeWithSingular, + yy : lv__relativeTimeWithPlural + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Montenegrin (me) + //! author : Miodrag Nikač <miodrag@restartit.me> : https://github.com/miodragnikac + + var me__translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jednog minuta'], + mm: ['minut', 'minuta', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mjesec', 'mjeseca', 'mjeseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = me__translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + me__translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var me = _moment__default.defineLocale('me', { + months: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'], + monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'], + weekdays: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'], + weekdaysShort: ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'], + weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'], + longDateFormat: { + LT: 'H:mm', + LTS : 'LT:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY LT', + LLLL: 'dddd, D. MMMM YYYY LT' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sjutra u] LT', + + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedjelje] [u] LT', + '[prošlog] [ponedjeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srijede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'nekoliko sekundi', + m : me__translator.translate, + mm : me__translator.translate, + h : me__translator.translate, + hh : me__translator.translate, + d : 'dan', + dd : me__translator.translate, + M : 'mjesec', + MM : me__translator.translate, + y : 'godinu', + yy : me__translator.translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : macedonian (mk) + //! author : Borislav Mickov : https://github.com/B0k0 + + var mk = _moment__default.defineLocale('mk', { + months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'), + weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'), + weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + 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 години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : malayalam (ml) + //! author : Floyd Pink : https://github.com/floydpink + + var ml = _moment__default.defineLocale('ml', { + months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'), + monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'), + weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'), + weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'), + weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'), + longDateFormat : { + LT : 'A h:mm -നു', + LTS : 'A h:mm:ss -നു', + 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 വർഷം' + }, + meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i, + isPM : function (input) { + return /^(ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'രാത്രി'; + } else if (hour < 12) { + return 'രാവിലെ'; + } else if (hour < 17) { + return 'ഉച്ച കഴിഞ്ഞ്'; + } else if (hour < 20) { + return 'വൈകുന്നേരം'; + } else { + return 'രാത്രി'; + } + } + }); + + //! moment.js locale configuration + //! locale : Marathi (mr) + //! author : Harshad Kale : https://github.com/kalehv + + var mr__symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + mr__numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var mr = _moment__default.defineLocale('mr', { + months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'), + monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'), + weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm वाजता', + LTS : 'A h:mm:ss वाजता', + 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 mr__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return mr__symbolMap[match]; + }); + }, + meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात्री') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सकाळी') { + return hour; + } else if (meridiem === 'दुपारी') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'सायंकाळी') { + return hour + 12; + } + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Bahasa Malaysia (ms-MY) + //! author : Weldan Jamili : https://github.com/weldan + + var ms_my = _moment__default.defineLocale('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', + LTS : 'LT.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] LT', + LLLL : 'dddd, D MMMM YYYY [pukul] LT' + }, + meridiemParse: /pagi|tengahari|petang|malam/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'tengahari') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'petang' || meridiem === 'malam') { + return hour + 12; + } + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Burmese (my) + //! author : Squar team, mysquar.com + + var my__symbolMap = { + '1': '၁', + '2': '၂', + '3': '၃', + '4': '၄', + '5': '၅', + '6': '၆', + '7': '၇', + '8': '၈', + '9': '၉', + '0': '၀' + }, my__numberMap = { + '၁': '1', + '၂': '2', + '၃': '3', + '၄': '4', + '၅': '5', + '၆': '6', + '၇': '7', + '၈': '8', + '၉': '9', + '၀': '0' + }; + + var my = _moment__default.defineLocale('my', { + months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'), + monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'), + weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'), + weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + + longDateFormat: { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + 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 my__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return my__symbolMap[match]; + }); + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 1st is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : norwegian bokmål (nb) + //! authors : Espen Hovlandsdal : https://github.com/rexxars + //! Sigurd Gartmann : https://github.com/sigurdga + + var nb = _moment__default.defineLocale('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_tirs_ons_tors_fre_lør'.split('_'), + weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), + longDateFormat : { + LT : 'H.mm', + LTS : 'LT.ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] LT', + LLLL : 'dddd D. MMMM YYYY [kl.] LT' + }, + calendar : { + sameDay: '[i dag kl.] LT', + nextDay: '[i morgen kl.] LT', + nextWeek: 'dddd [kl.] LT', + lastDay: '[i går kl.] LT', + lastWeek: '[forrige] dddd [kl.] 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' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : nepali/nepalese + //! author : suvash : https://github.com/suvash + + var ne__symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' + }, + ne__numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' + }; + + var ne = _moment__default.defineLocale('ne', { + months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'), + monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'), + weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'), + weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'), + weekdaysMin : 'आइ._सो._मङ्_बु._बि._शु._श.'.split('_'), + longDateFormat : { + LT : 'Aको h:mm बजे', + LTS : 'Aको h:mm:ss बजे', + 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 ne__numberMap[match]; + }); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return ne__symbolMap[match]; + }); + }, + meridiemParse: /राती|बिहान|दिउँसो|बेलुका|साँझ|राती/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'राती') { + return hour < 3 ? hour : hour + 12; + } else if (meridiem === 'बिहान') { + return hour; + } else if (meridiem === 'दिउँसो') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'बेलुका' || meridiem === 'साँझ') { + return hour + 12; + } + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : dutch (nl) + //! author : Joris Röling : https://github.com/jjupiter + + var nl__monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_'), + nl__monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_'); + + var nl = _moment__default.defineLocale('nl', { + months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return nl__monthsShortWithoutDots[m.month()]; + } else { + return nl__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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(ste|de)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : norwegian nynorsk (nn) + //! author : https://github.com/mechuwind + + var nn = _moment__default.defineLocale('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', + LTS : 'LT:ss', + L : 'DD.MM.YYYY', + 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åande] dddd [klokka] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : 'for %s sidan', + s : 'nokre sekund', + m : 'eit minutt', + mm : '%d minutt', + h : 'ein time', + hh : '%d timar', + d : 'ein dag', + dd : '%d dagar', + M : 'ein månad', + MM : '%d månader', + y : 'eit år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : 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 pl__plural(n) { + return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1); + } + function pl__translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'minuta' : 'minutę'; + case 'mm': + return result + (pl__plural(number) ? 'minuty' : 'minut'); + case 'h': + return withoutSuffix ? 'godzina' : 'godzinę'; + case 'hh': + return result + (pl__plural(number) ? 'godziny' : 'godzin'); + case 'MM': + return result + (pl__plural(number) ? 'miesiące' : 'miesięcy'); + case 'yy': + return result + (pl__plural(number) ? 'lata' : 'lat'); + } + } + + var pl = _moment__default.defineLocale('pl', { + months : function (momentToFormat, format) { + if (format === '') { + // Hack: if format empty we know this is used to generate + // RegExp by moment. Give then back both valid forms of months + // in RegExp ready format. + return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')'; + } else 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', + LTS : 'LT:ss', + 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 : pl__translate, + mm : pl__translate, + h : pl__translate, + hh : pl__translate, + d : '1 dzień', + dd : '%d dni', + M : 'miesiąc', + MM : pl__translate, + y : 'rok', + yy : pl__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : brazilian portuguese (pt-br) + //! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira + + var pt_br = _moment__default.defineLocale('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', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY [às] LT', + LLLL : 'dddd, D [de] MMMM [de] YYYY [às] 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' + }, + ordinalParse: /\d{1,2}º/, + ordinal : '%dº' + }); + + //! moment.js locale configuration + //! locale : portuguese (pt) + //! author : Jefferson : https://github.com/jalex79 + + var pt = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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 : 'há %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' + }, + ordinalParse: /\d{1,2}º/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : romanian (ro) + //! author : Vlad Gurdiga : https://github.com/gurdiga + //! author : Valentin Agachi : https://github.com/avaly + + function ro__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': 'minute', + 'hh': 'ore', + 'dd': 'zile', + 'MM': 'luni', + 'yy': 'ani' + }, + separator = ' '; + if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) { + separator = ' de '; + } + return number + separator + format[key]; + } + + var ro = _moment__default.defineLocale('ro', { + months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'), + monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._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', + LTS : 'LT:ss', + 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 : ro__relativeTimeWithPlural, + h : 'o oră', + hh : ro__relativeTimeWithPlural, + d : 'o zi', + dd : ro__relativeTimeWithPlural, + M : 'o lună', + MM : ro__relativeTimeWithPlural, + y : 'un an', + yy : ro__relativeTimeWithPlural + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : russian (ru) + //! author : Viktorminator : https://github.com/Viktorminator + //! Author : Menelion Elensúle : https://github.com/Oire + + function ru__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 ru__relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут', + 'hh': 'час_часа_часов', + 'dd': 'день_дня_дней', + 'MM': 'месяц_месяца_месяцев', + 'yy': 'год_года_лет' + }; + if (key === 'm') { + return withoutSuffix ? 'минута' : 'минуту'; + } + else { + return number + ' ' + ru__plural(format[key], +number); + } + } + function ru__monthsCaseReplace(m, format) { + var months = { + 'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + 'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_') + }, + nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; + } + function ru__monthsShortCaseReplace(m, format) { + var monthsShort = { + 'nominative': 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'), + 'accusative': 'янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек'.split('_') + }, + nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return monthsShort[nounCase][m.month()]; + } + function ru__weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), + 'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_') + }, + nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/).test(format) ? + 'accusative' : + 'nominative'; + return weekdays[nounCase][m.day()]; + } + + var ru = _moment__default.defineLocale('ru', { + months : ru__monthsCaseReplace, + monthsShort : ru__monthsShortCaseReplace, + weekdays : ru__weekdaysCaseReplace, + weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + monthsParse : [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[й|я]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i], + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 (now) { + if (now.week() !== this.week()) { + 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'; + } + } else { + if (this.day() === 2) { + return '[Во] dddd [в] LT'; + } else { + return '[В] dddd [в] LT'; + } + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'через %s', + past : '%s назад', + s : 'несколько секунд', + m : ru__relativeTimeWithPlural, + mm : ru__relativeTimeWithPlural, + h : 'час', + hh : ru__relativeTimeWithPlural, + d : 'день', + dd : ru__relativeTimeWithPlural, + M : 'месяц', + MM : ru__relativeTimeWithPlural, + y : 'год', + yy : ru__relativeTimeWithPlural + }, + meridiemParse: /ночи|утра|дня|вечера/i, + isPM : function (input) { + return /^(дня|вечера)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночи'; + } else if (hour < 12) { + return 'утра'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечера'; + } + }, + ordinalParse: /\d{1,2}-(й|го|я)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Sinhalese (si) + //! author : Sampath Sitinamaluwa : https://github.com/sampathsris + + var si = _moment__default.defineLocale('si', { + months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'), + monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'), + weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'), + weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්රහ_සිකු_සෙන'.split('_'), + weekdaysMin : 'ඉ_ස_අ_බ_බ්ර_සි_සෙ'.split('_'), + longDateFormat : { + LT : 'a h:mm', + LTS : 'a h:mm:ss', + L : 'YYYY/MM/DD', + LL : 'YYYY MMMM D', + LLL : 'YYYY MMMM D, LT', + LLLL : 'YYYY MMMM D [වැනි] dddd, LTS' + }, + 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' + }, + ordinalParse: /\d{1,2} වැනි/, + ordinal : function (number) { + return number + ' වැනි'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'ප.ව.' : 'පස් වරු'; + } else { + return isLower ? 'පෙ.ව.' : 'පෙර වරු'; + } + } + }); + + //! moment.js locale configuration + //! locale : slovak (sk) + //! author : Martin Minka : https://github.com/k2s + //! based on work of petrbela : https://github.com/petrbela + + var sk__months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_'), + sk__monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_'); + function sk__plural(n) { + return (n > 1) && (n < 5); + } + function sk__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 + (sk__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 + (sk__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 + (sk__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 + (sk__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 + (sk__plural(number) ? 'roky' : 'rokov'); + } else { + return result + 'rokmi'; + } + break; + } + } + + var sk = _moment__default.defineLocale('sk', { + months : sk__months, + monthsShort : sk__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; + }(sk__months, sk__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', + LTS : 'LT:ss', + 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 : sk__translate, + m : sk__translate, + mm : sk__translate, + h : sk__translate, + hh : sk__translate, + d : sk__translate, + dd : sk__translate, + M : sk__translate, + MM : sk__translate, + y : sk__translate, + yy : sk__translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : slovenian (sl) + //! author : Robert Sedovšek : https://github.com/sedovsek + + function sl__processRelativeTime(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami'; + case 'm': + return withoutSuffix ? 'ena minuta' : 'eno minuto'; + case 'mm': + if (number === 1) { + result += withoutSuffix ? 'minuta' : 'minuto'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'minuti' : 'minutama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'minute' : 'minutami'; + } else { + result += withoutSuffix || isFuture ? 'minut' : 'minutami'; + } + return result; + case 'h': + return withoutSuffix ? 'ena ura' : 'eno uro'; + case 'hh': + if (number === 1) { + result += withoutSuffix ? 'ura' : 'uro'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'uri' : 'urama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'ure' : 'urami'; + } else { + result += withoutSuffix || isFuture ? 'ur' : 'urami'; + } + return result; + case 'd': + return withoutSuffix || isFuture ? 'en dan' : 'enim dnem'; + case 'dd': + if (number === 1) { + result += withoutSuffix || isFuture ? 'dan' : 'dnem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'dni' : 'dnevoma'; + } else { + result += withoutSuffix || isFuture ? 'dni' : 'dnevi'; + } + return result; + case 'M': + return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem'; + case 'MM': + if (number === 1) { + result += withoutSuffix || isFuture ? 'mesec' : 'mesecem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'meseca' : 'mesecema'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'mesece' : 'meseci'; + } else { + result += withoutSuffix || isFuture ? 'mesecev' : 'meseci'; + } + return result; + case 'y': + return withoutSuffix || isFuture ? 'eno leto' : 'enim letom'; + case 'yy': + if (number === 1) { + result += withoutSuffix || isFuture ? 'leto' : 'letom'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'leti' : 'letoma'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'leta' : 'leti'; + } else { + result += withoutSuffix || isFuture ? 'let' : 'leti'; + } + return result; + } + } + + var sl = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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: + return '[prejšnjo] [nedeljo] [ob] LT'; + case 3: + return '[prejšnjo] [sredo] [ob] LT'; + case 6: + return '[prejšnjo] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prejšnji] dddd [ob] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'čez %s', + past : 'pred %s', + s : sl__processRelativeTime, + m : sl__processRelativeTime, + mm : sl__processRelativeTime, + h : sl__processRelativeTime, + hh : sl__processRelativeTime, + d : sl__processRelativeTime, + dd : sl__processRelativeTime, + M : sl__processRelativeTime, + MM : sl__processRelativeTime, + y : sl__processRelativeTime, + yy : sl__processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Albanian (sq) + //! author : Flakërim Ismani : https://github.com/flakerimi + //! author: Menelion Elensúle: https://github.com/Oire (tests) + //! author : Oerd Cukalla : https://github.com/oerd (fixes) + + var sq = _moment__default.defineLocale('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 Martë_E Mërkurë_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('_'), + meridiemParse: /PD|MD/, + isPM: function (input) { + return input.charAt(0) === 'M'; + }, + meridiem : function (hours, minutes, isLower) { + return hours < 12 ? 'PD' : 'MD'; + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : '[Nesër në] LT', + nextWeek : 'dddd [në] LT', + lastDay : '[Dje në] LT', + lastWeek : 'dddd [e kaluar në] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'në %s', + past : '%s më parë', + s : 'disa sekonda', + m : 'një minutë', + mm : '%d minuta', + h : 'një orë', + hh : '%d orë', + d : 'një ditë', + dd : '%d ditë', + M : 'një muaj', + MM : '%d muaj', + y : 'një vit', + yy : '%d vite' + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Serbian-cyrillic (sr-cyrl) + //! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + + var sr_cyrl__translator = { + words: { //Different grammatical cases + m: ['један минут', 'једне минуте'], + mm: ['минут', 'минуте', 'минута'], + h: ['један сат', 'једног сата'], + hh: ['сат', 'сата', 'сати'], + dd: ['дан', 'дана', 'дана'], + MM: ['месец', 'месеца', 'месеци'], + yy: ['година', 'године', 'година'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = sr_cyrl__translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + sr_cyrl__translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var sr_cyrl = _moment__default.defineLocale('sr-cyrl', { + months: ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'], + monthsShort: ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'], + weekdays: ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'], + weekdaysShort: ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'], + weekdaysMin: ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'], + longDateFormat: { + LT: 'H:mm', + LTS : 'LT:ss', + 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: function () { + switch (this.day()) { + case 0: + return '[у] [недељу] [у] LT'; + case 3: + return '[у] [среду] [у] LT'; + case 6: + return '[у] [суботу] [у] LT'; + case 1: + case 2: + case 4: + case 5: + return '[у] dddd [у] LT'; + } + }, + lastDay : '[јуче у] LT', + lastWeek : function () { + var lastWeekDays = [ + '[прошле] [недеље] [у] LT', + '[прошлог] [понедељка] [у] LT', + '[прошлог] [уторка] [у] LT', + '[прошле] [среде] [у] LT', + '[прошлог] [четвртка] [у] LT', + '[прошлог] [петка] [у] LT', + '[прошле] [суботе] [у] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'за %s', + past : 'пре %s', + s : 'неколико секунди', + m : sr_cyrl__translator.translate, + mm : sr_cyrl__translator.translate, + h : sr_cyrl__translator.translate, + hh : sr_cyrl__translator.translate, + d : 'дан', + dd : sr_cyrl__translator.translate, + M : 'месец', + MM : sr_cyrl__translator.translate, + y : 'годину', + yy : sr_cyrl__translator.translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : Serbian-latin (sr) + //! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + + var sr__translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jedne minute'], + mm: ['minut', 'minute', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mesec', 'meseca', 'meseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = sr__translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + sr__translator.correctGrammaticalCase(number, wordKey); + } + } + }; + + var sr = _moment__default.defineLocale('sr', { + months: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'], + monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'], + weekdays: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'], + weekdaysShort: ['ned.', 'pon.', 'uto.', 'sre.', 'čet.', 'pet.', 'sub.'], + weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'], + longDateFormat: { + LT: 'H:mm', + LTS : 'LT:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY LT', + LLLL: 'dddd, D. MMMM YYYY LT' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sutra u] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedelju] [u] LT'; + case 3: + return '[u] [sredu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedelje] [u] LT', + '[prošlog] [ponedeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'pre %s', + s : 'nekoliko sekundi', + m : sr__translator.translate, + mm : sr__translator.translate, + h : sr__translator.translate, + hh : sr__translator.translate, + d : 'dan', + dd : sr__translator.translate, + M : 'mesec', + MM : sr__translator.translate, + y : 'godinu', + yy : sr__translator.translate + }, + ordinalParse: /\d{1,2}\./, + 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. + } + }); + + //! moment.js locale configuration + //! locale : swedish (sv) + //! author : Jens Alm : https://github.com/ulmus + + var sv = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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: '[På] dddd LT', + lastWeek: '[I] dddd[s] 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' + }, + ordinalParse: /\d{1,2}(e|a)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : tamil (ta) + //! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404 + + var ta = _moment__default.defineLocale('ta', { + months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'), + weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'), + weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 ஆண்டுகள்' + }, + ordinalParse: /\d{1,2}வது/, + ordinal : function (number) { + return number + 'வது'; + }, + // refer http://ta.wikipedia.org/s/1er1 + meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/, + meridiem : function (hour, minute, isLower) { + if (hour < 2) { + return ' யாமம்'; + } else if (hour < 6) { + return ' வைகறை'; // வைகறை + } else if (hour < 10) { + return ' காலை'; // காலை + } else if (hour < 14) { + return ' நண்பகல்'; // நண்பகல் + } else if (hour < 18) { + return ' எற்பாடு'; // எற்பாடு + } else if (hour < 22) { + return ' மாலை'; // மாலை + } else { + return ' யாமம்'; + } + }, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'யாமம்') { + return hour < 2 ? hour : hour + 12; + } else if (meridiem === 'வைகறை' || meridiem === 'காலை') { + return hour; + } else if (meridiem === 'நண்பகல்') { + return hour >= 10 ? hour : hour + 12; + } else { + return hour + 12; + } + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : thai (th) + //! author : Kridsada Thanabulpong : https://github.com/sirn + + var th = _moment__default.defineLocale('th', { + months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'), + monthsShort : 'มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา'.split('_'), + weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'), + weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference + weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'), + longDateFormat : { + LT : 'H นาฬิกา m นาที', + LTS : 'LT s วินาที', + L : 'YYYY/MM/DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY เวลา LT', + LLLL : 'วันddddที่ D MMMM YYYY เวลา LT' + }, + meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/, + isPM: function (input) { + return input === 'หลังเที่ยง'; + }, + 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 ปี' + } + }); + + //! moment.js locale configuration + //! locale : Tagalog/Filipino (tl-ph) + //! author : Dan Hagman + + var tl_ph = _moment__default.defineLocale('tl-ph', { + months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'), + monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'), + weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'), + weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'), + weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'MM/D/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY LT', + LLLL : 'dddd, MMMM DD, YYYY LT' + }, + calendar : { + sameDay: '[Ngayon sa] LT', + nextDay: '[Bukas sa] LT', + nextWeek: 'dddd [sa] LT', + lastDay: '[Kahapon sa] LT', + lastWeek: 'dddd [huling linggo] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'sa loob ng %s', + past : '%s ang nakalipas', + s : 'ilang segundo', + m : 'isang minuto', + mm : '%d minuto', + h : 'isang oras', + hh : '%d oras', + d : 'isang araw', + dd : '%d araw', + M : 'isang buwan', + MM : '%d buwan', + y : 'isang taon', + yy : '%d taon' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : turkish (tr) + //! authors : Erhan Gundogan : https://github.com/erhangundogan, + //! Burak Yiğit Kaya: https://github.com/BYK + + var tr__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 tr = _moment__default.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/, + 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 + (tr__suffixes[a] || tr__suffixes[b] || tr__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. + } + }); + + //! moment.js locale configuration + //! locale : Morocco Central Atlas Tamaziɣt in Latin (tzm-latn) + //! author : Abdel Said : https://github.com/abdelsaid + + var tzm_latn = _moment__default.defineLocale('tzm-latn', { + 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', + LTS : 'LT:ss', + 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. + } + }); + + //! moment.js locale configuration + //! locale : Morocco Central Atlas Tamaziɣt (tzm) + //! author : Abdel Said : https://github.com/abdelsaid + + var tzm = _moment__default.defineLocale('tzm', { + months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS: 'LT:ss', + 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. + } + }); + + //! moment.js locale configuration + //! locale : ukrainian (uk) + //! author : zemlanin : https://github.com/zemlanin + //! Author : Menelion Elensúle : https://github.com/Oire + + function uk__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 uk__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 + ' ' + uk__plural(format[key], +number); + } + } + function uk__monthsCaseReplace(m, format) { + var months = { + 'nominative': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_'), + 'accusative': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_') + }, + nounCase = (/D[oD]? *MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; + } + function uk__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'; + }; + } + + var uk = _moment__default.defineLocale('uk', { + months : uk__monthsCaseReplace, + monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'), + weekdays : uk__weekdaysCaseReplace, + weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : uk__relativeTimeWithPlural, + mm : uk__relativeTimeWithPlural, + h : 'годину', + hh : uk__relativeTimeWithPlural, + d : 'день', + dd : uk__relativeTimeWithPlural, + M : 'місяць', + MM : uk__relativeTimeWithPlural, + y : 'рік', + yy : uk__relativeTimeWithPlural + }, + // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason + meridiemParse: /ночі|ранку|дня|вечора/, + isPM: function (input) { + return /^(дня|вечора)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночі'; + } else if (hour < 12) { + return 'ранку'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечора'; + } + }, + ordinalParse: /\d{1,2}-(й|го)/, + 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. + } + }); + + //! moment.js locale configuration + //! locale : uzbek (uz) + //! author : Sardor Muminov : https://github.com/muminoff + + var uz = _moment__default.defineLocale('uz', { + months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'), + weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'), + weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'), + weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'D MMMM YYYY, dddd 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 : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 4th is the first week of the year. + } + }); + + //! moment.js locale configuration + //! locale : vietnamese (vi) + //! author : Bang Nguyen : https://github.com/bangnk + + var vi = _moment__default.defineLocale('vi', { + months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'), + monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'), + weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'), + weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM [năm] YYYY', + LLL : 'D MMMM [năm] YYYY LT', + LLLL : 'dddd, D MMMM [năm] YYYY LT', + l : 'DD/M/YYYY', + ll : 'D MMM YYYY', + lll : 'D MMM YYYY LT', + llll : 'ddd, D MMM YYYY LT' + }, + calendar : { + sameDay: '[Hôm nay lúc] LT', + nextDay: '[Ngày mai lúc] LT', + nextWeek: 'dddd [tuần tới lúc] LT', + lastDay: '[Hôm qua lúc] LT', + lastWeek: 'dddd [tuần rồi lúc] LT', + sameElse: 'L' + }, + relativeTime : { + future : '%s tới', + past : '%s trước', + s : 'vài giây', + m : 'một phút', + mm : '%d phút', + h : 'một giờ', + hh : '%d giờ', + d : 'một ngày', + dd : '%d ngày', + M : 'một tháng', + MM : '%d tháng', + y : 'một năm', + yy : '%d năm' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + 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. + } + }); + + //! moment.js locale configuration + //! locale : chinese (zh-cn) + //! author : suupic : https://github.com/suupic + //! author : Zeno Zeng : https://github.com/zenozeng + + var zh_cn = _moment__default.defineLocale('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分', + LTS : 'Ah点m分s秒', + L : 'YYYY-MM-DD', + LL : 'YYYY年MMMD日', + LLL : 'YYYY年MMMD日LT', + LLLL : 'YYYY年MMMD日ddddLT', + l : 'YYYY-MM-DD', + ll : 'YYYY年MMMD日', + lll : 'YYYY年MMMD日LT', + llll : 'YYYY年MMMD日ddddLT' + }, + meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '凌晨' || meridiem === '早上' || + meridiem === '上午') { + return hour; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } else { + // '中午' + return hour >= 11 ? hour : hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 600) { + return '凌晨'; + } else if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : function () { + return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT'; + }, + nextDay : function () { + return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT'; + }, + lastDay : function () { + return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT'; + }, + nextWeek : function () { + var startOfWeek, prefix; + startOfWeek = _moment__default().startOf('week'); + prefix = this.unix() - startOfWeek.unix() >= 7 * 24 * 3600 ? '[下]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + lastWeek : function () { + var startOfWeek, prefix; + startOfWeek = _moment__default().startOf('week'); + prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + sameElse : 'LL' + }, + ordinalParse: /\d{1,2}(日|月|周)/, + 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 年' + }, + week : { + // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 + 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. + } + }); + + //! moment.js locale configuration + //! locale : traditional chinese (zh-tw) + //! author : Ben : https://github.com/ben-lin + + var zh_tw = _moment__default.defineLocale('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分', + LTS : 'Ah點m分s秒', + 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' + }, + meridiemParse: /早上|上午|中午|下午|晚上/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '早上' || meridiem === '上午') { + return hour; + } else if (meridiem === '中午') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + ordinalParse: /\d{1,2}(日|月|週)/, + 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年' + } + }); + + var moment_with_locales = _moment__default; + + return moment_with_locales; + +}));
\ No newline at end of file diff --git a/bower_components/moment/min/tests.js b/bower_components/moment/min/tests.js new file mode 100644 index 0000000..0d7bb95 --- /dev/null +++ b/bower_components/moment/min/tests.js @@ -0,0 +1,39537 @@ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('af'); + + test('parse', function (assert) { + var tests = 'Januarie Jan_Februarie Feb_Maart Mar_April Apr_Mei Mei_Junie Jun_Julie Jul_Augustus Aug_September Sep_Oktober Okt_November Nov_Desember Des'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Sondag, Februarie 14de 2010, 3:25:50 nm'], + ['ddd, hA', 'Son, 3NM'], + ['M Mo MM MMMM MMM', '2 2de 02 Februarie Feb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14de 14'], + ['d do dddd ddd dd', '0 0de Sondag Son So'], + ['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', 'nm NM'], + ['[the] DDDo [day of the year]', 'the 45ste day of the year'], + ['LT', '15:25'], + ['LTS', '15:25:50'], + ['L', '14/02/2010'], + ['LL', '14 Februarie 2010'], + ['LLL', '14 Februarie 2010 15:25'], + ['LLLL', 'Sondag, 14 Februarie 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 Feb 2010'], + ['lll', '14 Feb 2010 15:25'], + ['llll', 'Son, 14 Feb 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1ste', '1ste'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2de', '2de'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3de', '3de'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4de', '4de'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5de', '5de'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6de', '6de'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7de', '7de'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8ste', '8ste'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9de', '9de'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10de', '10de'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11de', '11de'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12de', '12de'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13de', '13de'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14de', '14de'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15de', '15de'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16de', '16de'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17de', '17de'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18de', '18de'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19de', '19de'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20ste', '20ste'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21ste', '21ste'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22ste', '22ste'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23ste', '23ste'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24ste', '24ste'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25ste', '25ste'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26ste', '26ste'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27ste', '27ste'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28ste', '28ste'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29ste', '29ste'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30ste', '30ste'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31ste', '31ste'); + }); + + test('format month', function (assert) { + var expected = 'Januarie Jan_Februarie Feb_Maart Mar_April Apr_Mei Mei_Junie Jun_Julie Jul_Augustus Aug_September Sep_Oktober Okt_November Nov_Desember Des'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Sondag Son So_Maandag Maa Ma_Dinsdag Din Di_Woensdag Woe Wo_Donderdag Don Do_Vrydag Vry Vr_Saterdag Sat Sa'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), '\'n paar sekondes', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), '\'n minuut', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), '\'n minuut', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minute', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minute', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), '\'n uur', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), '\'n uur', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 ure', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 ure', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 ure', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), '\'n dag', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), '\'n dag', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dae', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), '\'n dag', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dae', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dae', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), '\'n maand', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), '\'n maand', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), '\'n maand', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 maande', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 maande', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 maande', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), '\'n maand', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 maande', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), '\'n jaar', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 jaar', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), '\'n jaar', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 jaar', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'oor \'n paar sekondes', 'prefix'); + assert.equal(moment(0).from(30000), '\'n paar sekondes gelede', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), '\'n paar sekondes gelede', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'oor \'n paar sekondes', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'oor 5 dae', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Vandag om 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Vandag om 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Vandag om 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Môre om 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Vandag om 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Gister om 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [om] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [om] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [om] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[Laas] dddd [om] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[Laas] dddd [om] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[Laas] dddd [om] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52ste', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1ste', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1ste', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2de', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2de', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ar-ma'); + + test('parse', function (assert) { + var tests = 'يناير:يناير_فبراير:فبراير_مارس:مارس_أبريل:أبريل_ماي:ماي_يونيو:يونيو_يوليوز:يوليوز_غشت:غشت_شتنبر:شتنبر_أكتوبر:أكتوبر_نونبر:نونبر_دجنبر:دجنبر'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LT', '15:25'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + }); + + test('format month', function (assert) { + var expected = 'يناير يناير_فبراير فبراير_مارس مارس_أبريل أبريل_ماي ماي_يونيو يونيو_يوليوز يوليوز_غشت غشت_شتنبر شتنبر_أكتوبر أكتوبر_نونبر نونبر_دجنبر دجنبر'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'الأحد احد ح_الإتنين اتنين ن_الثلاثاء ثلاثاء ث_الأربعاء اربعاء ر_الخميس خميس خ_الجمعة جمعة ج_السبت سبت س'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'ثوان', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'دقيقة', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'دقيقة', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 دقائق', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 دقائق', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ساعة', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ساعة', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 ساعات', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 ساعات', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 ساعات', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'يوم', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'يوم', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 أيام', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'يوم', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 أيام', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 أيام', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'شهر', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'شهر', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'شهر', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 أشهر', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 أشهر', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 أشهر', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'شهر', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 أشهر', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'سنة', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 سنوات', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'سنة', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 سنوات', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'في ثوان', 'prefix'); + assert.equal(moment(0).from(30000), 'منذ ثوان', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'منذ ثوان', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'في ثوان', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'في 5 أيام', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'اليوم على الساعة 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'اليوم على الساعة 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'اليوم على الساعة 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'غدا على الساعة 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'اليوم على الساعة 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'أمس على الساعة 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 31]).week(), 1, 'Dec 31 2011 should be week 1'); + assert.equal(moment([2012, 0, 6]).week(), 1, 'Jan 6 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 2, 'Jan 7 2012 should be week 2'); + assert.equal(moment([2012, 0, 13]).week(), 2, 'Jan 13 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 3, 'Jan 14 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 30]).week(), 1, 'Dec 30 2006 should be week 1'); + assert.equal(moment([2007, 0, 5]).week(), 1, 'Jan 5 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 2, 'Jan 6 2007 should be week 2'); + assert.equal(moment([2007, 0, 12]).week(), 2, 'Jan 12 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 3, 'Jan 13 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 1, 'Dec 29 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 4]).week(), 1, 'Jan 4 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 2, 'Jan 5 2008 should be week 2'); + assert.equal(moment([2008, 0, 11]).week(), 2, 'Jan 11 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 3, 'Jan 12 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 28]).week(), 1, 'Dec 28 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 3]).week(), 1, 'Jan 3 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 2, 'Jan 4 2003 should be week 2'); + assert.equal(moment([2003, 0, 10]).week(), 2, 'Jan 10 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 3, 'Jan 11 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 27]).week(), 1, 'Dec 27 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 2]).week(), 1, 'Jan 2 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 2, 'Jan 3 2009 should be week 2'); + assert.equal(moment([2009, 0, 9]).week(), 2, 'Jan 9 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 3, 'Jan 10 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 26]).week(), 1, 'Dec 26 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 2, 'Jan 2 2010 should be week 2'); + assert.equal(moment([2010, 0, 8]).week(), 2, 'Jan 8 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 3, 'Jan 9 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 7]).week(), 1, 'Jan 7 2011 should be week 1'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 14]).week(), 2, 'Jan 14 2011 should be week 2'); + assert.equal(moment([2011, 0, 15]).week(), 3, 'Jan 15 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 31]).format('w ww wo'), '1 01 1', 'Dec 31 2011 should be week 1'); + assert.equal(moment([2012, 0, 6]).format('w ww wo'), '1 01 1', 'Jan 6 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '2 02 2', 'Jan 7 2012 should be week 2'); + assert.equal(moment([2012, 0, 13]).format('w ww wo'), '2 02 2', 'Jan 13 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '3 03 3', 'Jan 14 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ar-sa'); + + test('parse', function (assert) { + var tests = 'يناير:يناير_فبراير:فبراير_مارس:مارس_أبريل:أبريل_مايو:مايو_يونيو:يونيو_يوليو:يوليو_أغسطس:أغسطس_سبتمبر:سبتمبر_أكتوبر:أكتوبر_نوفمبر:نوفمبر_ديسمبر:ديسمبر'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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', 'م م'], + ['[the] DDDo [day of the year]', 'the ٤٥ day of the year'], + ['LT', '١٥:٢٥'], + ['LTS', '١٥:٢٥:٥٠'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '١', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '٢', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '٣', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '٤', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '٥', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '٦', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '٧', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '٨', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '٩', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '١٠', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '١١', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '١٢', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '١٣', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '١٤', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '١٥', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '١٦', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '١٧', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '١٨', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '١٩', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '٢٠', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '٢١', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '٢٢', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '٢٣', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '٢٤', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '٢٥', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '٢٦', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '٢٧', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '٢٨', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '٢٩', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '٣٠', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '٣١', '31'); + }); + + test('format month', function (assert) { + var expected = 'يناير يناير_فبراير فبراير_مارس مارس_أبريل أبريل_مايو مايو_يونيو يونيو_يوليو يوليو_أغسطس أغسطس_سبتمبر سبتمبر_أكتوبر أكتوبر_نوفمبر نوفمبر_ديسمبر ديسمبر'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'الأحد أحد ح_الإثنين إثنين ن_الثلاثاء ثلاثاء ث_الأربعاء أربعاء ر_الخميس خميس خ_الجمعة جمعة ج_السبت سبت س'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'ثوان', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'دقيقة', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'دقيقة', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '٢ دقائق', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '٤٤ دقائق', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ساعة', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ساعة', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '٢ ساعات', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '٥ ساعات', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '٢١ ساعات', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'يوم', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'يوم', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '٢ أيام', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'يوم', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '٥ أيام', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '٢٥ أيام', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'شهر', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'شهر', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'شهر', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '٢ أشهر', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '٢ أشهر', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '٣ أشهر', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'شهر', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '٥ أشهر', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'سنة', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '٢ سنوات', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'سنة', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '٥ سنوات', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'في ثوان', 'prefix'); + assert.equal(moment(0).from(30000), 'منذ ثوان', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'منذ ثوان', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'في ثوان', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'في ٥ أيام', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'اليوم على الساعة ٠٢:٠٠', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'اليوم على الساعة ٠٢:٢٥', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'اليوم على الساعة ٠٣:٠٠', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'غدا على الساعة ٠٢:٠٠', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'اليوم على الساعة ٠١:٠٠', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'أمس على الساعة ٠٢:٠٠', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 31]).week(), 1, 'Dec 31 2011 should be week 1'); + assert.equal(moment([2012, 0, 6]).week(), 1, 'Jan 6 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 2, 'Jan 7 2012 should be week 2'); + assert.equal(moment([2012, 0, 13]).week(), 2, 'Jan 13 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 3, 'Jan 14 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 30]).week(), 1, 'Dec 30 2006 should be week 1'); + assert.equal(moment([2007, 0, 5]).week(), 1, 'Jan 5 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 2, 'Jan 6 2007 should be week 2'); + assert.equal(moment([2007, 0, 12]).week(), 2, 'Jan 12 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 3, 'Jan 13 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 1, 'Dec 29 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 4]).week(), 1, 'Jan 4 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 2, 'Jan 5 2008 should be week 2'); + assert.equal(moment([2008, 0, 11]).week(), 2, 'Jan 11 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 3, 'Jan 12 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 28]).week(), 1, 'Dec 28 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 3]).week(), 1, 'Jan 3 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 2, 'Jan 4 2003 should be week 2'); + assert.equal(moment([2003, 0, 10]).week(), 2, 'Jan 10 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 3, 'Jan 11 2003 should be week 3'); + + assert.equal(moment('2003 1 6', 'gggg w d').format('YYYY-MM-DD'), '٢٠٠٢-١٢-٢٨', 'Week 1 of 2003 should be Dec 28 2002'); + assert.equal(moment('2003 1 0', 'gggg w e').format('YYYY-MM-DD'), '٢٠٠٢-١٢-٢٨', 'Week 1 of 2003 should be Dec 28 2002'); + assert.equal(moment('2003 1 6', 'gggg w d').format('gggg w d'), '٢٠٠٣ ١ ٦', 'Saturday of week 1 of 2003 parsed should be formatted as 2003 1 6'); + assert.equal(moment('2003 1 0', 'gggg w e').format('gggg w e'), '٢٠٠٣ ١ ٠', '1st day of week 1 of 2003 parsed should be formatted as 2003 1 0'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 27]).week(), 1, 'Dec 27 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 2]).week(), 1, 'Jan 2 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 2, 'Jan 3 2009 should be week 2'); + assert.equal(moment([2009, 0, 9]).week(), 2, 'Jan 9 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 3, 'Jan 10 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 26]).week(), 1, 'Dec 26 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 2, 'Jan 2 2010 should be week 2'); + assert.equal(moment([2010, 0, 8]).week(), 2, 'Jan 8 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 3, 'Jan 9 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 7]).week(), 1, 'Jan 7 2011 should be week 1'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 14]).week(), 2, 'Jan 14 2011 should be week 2'); + assert.equal(moment([2011, 0, 15]).week(), 3, 'Jan 15 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 31]).format('w ww wo'), '١ ٠١ ١', 'Dec 31 2011 should be week 1'); + assert.equal(moment([2012, 0, 6]).format('w ww wo'), '١ ٠١ ١', 'Jan 6 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '٢ ٠٢ ٢', 'Jan 7 2012 should be week 2'); + assert.equal(moment([2012, 0, 13]).format('w ww wo'), '٢ ٠٢ ٢', 'Jan 13 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '٣ ٠٣ ٣', 'Jan 14 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ar-tn'); + + test('parse', function (assert) { + var tests = 'جانفي:جانفي_فيفري:فيفري_مارس:مارس_أفريل:أفريل_ماي:ماي_جوان:جوان_جويلية:جويلية_أوت:أوت_سبتمبر:سبتمبر_أكتوبر:أكتوبر_نوفمبر:نوفمبر_ديسمبر:ديسمبر'.split('_'), + i; + + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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', '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'], + ['LT', '15:25'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + }); + + test('format month', function (assert) { + var expected = 'جانفي جانفي_فيفري فيفري_مارس مارس_أفريل أفريل_ماي ماي_جوان جوان_جويلية جويلية_أوت أوت_سبتمبر سبتمبر_أكتوبر أكتوبر_نوفمبر نوفمبر_ديسمبر ديسمبر'.split('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'الأحد أحد ح_الإثنين إثنين ن_الثلاثاء ثلاثاء ث_الأربعاء أربعاء ر_الخميس خميس خ_الجمعة جمعة ج_السبت سبت س'.split('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({ + s: 44 + }), true), 'ثوان', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + s: 45 + }), true), 'دقيقة', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + s: 89 + }), true), 'دقيقة', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + s: 90 + }), true), '2 دقائق', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + m: 44 + }), true), '44 دقائق', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + m: 45 + }), true), 'ساعة', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + m: 89 + }), true), 'ساعة', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + m: 90 + }), true), '2 ساعات', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + h: 5 + }), true), '5 ساعات', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + h: 21 + }), true), '21 ساعات', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + h: 22 + }), true), 'يوم', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + h: 35 + }), true), 'يوم', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + h: 36 + }), true), '2 أيام', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 1 + }), true), 'يوم', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 5 + }), true), '5 أيام', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 25 + }), true), '25 أيام', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 26 + }), true), 'شهر', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 30 + }), true), 'شهر', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 43 + }), true), 'شهر', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 46 + }), true), '2 أشهر', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 74 + }), true), '2 أشهر', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 76 + }), true), '3 أشهر', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + M: 1 + }), true), 'شهر', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + M: 5 + }), true), '5 أشهر', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 345 + }), true), 'سنة', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 548 + }), true), '2 سنوات', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + y: 1 + }), true), 'سنة', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + y: 5 + }), true), '5 سنوات', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'في ثوان', 'prefix'); + assert.equal(moment(0).from(30000), 'منذ ثوان', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'منذ ثوان', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({ + s: 30 + }).fromNow(), 'في ثوان', 'in a few seconds'); + assert.equal(moment().add({ + d: 5 + }).fromNow(), 'في 5 أيام', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'اليوم على الساعة 02:00', 'today at the same time'); + assert.equal(moment(a).add({ + m: 25 + }).calendar(), 'اليوم على الساعة 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({ + h: 1 + }).calendar(), 'اليوم على الساعة 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({ + d: 1 + }).calendar(), 'غدا على الساعة 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({ + h: 1 + }).calendar(), 'اليوم على الساعة 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({ + d: 1 + }).calendar(), 'أمس على الساعة 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({ + d: i + }); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({ + d: i + }); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [على الساعة] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({ + w: 1 + }), + weeksFromNow = moment().add({ + w: 1 + }); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({ + w: 2 + }); + weeksFromNow = moment().add({ + w: 2 + }); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ar'); + + var months = [ + 'كانون الثاني يناير', + 'شباط فبراير', + 'آذار مارس', + 'نيسان أبريل', + 'أيار مايو', + 'حزيران يونيو', + 'تموز يوليو', + 'آب أغسطس', + 'أيلول سبتمبر', + 'تشرين الأول أكتوبر', + 'تشرين الثاني نوفمبر', + 'كانون الأول ديسمبر' + ]; + + test('parse', function (assert) { + var tests = months, i; + function equalTest(input, mmm, i) { + assert.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], 'MMM', i); + equalTest(tests[i], 'MMMM', i); + equalTest(tests[i], 'MMMM', i); + equalTest(tests[i].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i].toLocaleUpperCase(), 'MMMM', i); + } + }); + + test('format', function (assert) { + 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', 'م م'], + ['[the] DDDo [day of the year]', 'the ٤٥ day of the year'], + ['LT', '١٥:٢٥'], + ['LTS', '١٥:٢٥:٥٠'], + ['L', '١٤/\u200f٢/\u200f٢٠١٠'], + ['LL', '١٤ شباط فبراير ٢٠١٠'], + ['LLL', '١٤ شباط فبراير ٢٠١٠ ١٥:٢٥'], + ['LLLL', 'الأحد ١٤ شباط فبراير ٢٠١٠ ١٥:٢٥'], + ['l', '١٤/\u200f٢/\u200f٢٠١٠'], + ['ll', '١٤ شباط فبراير ٢٠١٠'], + ['lll', '١٤ شباط فبراير ٢٠١٠ ١٥:٢٥'], + ['llll', 'أحد ١٤ شباط فبراير ٢٠١٠ ١٥:٢٥'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '١', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '٢', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '٣', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '٤', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '٥', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '٦', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '٧', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '٨', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '٩', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '١٠', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '١١', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '١٢', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '١٣', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '١٤', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '١٥', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '١٦', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '١٧', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '١٨', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '١٩', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '٢٠', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '٢١', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '٢٢', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '٢٣', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '٢٤', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '٢٥', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '٢٦', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '٢٧', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '٢٨', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '٢٩', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '٣٠', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '٣١', '31'); + }); + + test('format month', function (assert) { + var expected = months, i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM'), expected[i], expected[i]); + assert.equal(moment([2011, i, 1]).format('MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'الأحد أحد ح_الإثنين إثنين ن_الثلاثاء ثلاثاء ث_الأربعاء أربعاء ر_الخميس خميس خ_الجمعة جمعة ج_السبت سبت س'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), '٤٤ ثانية', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'دقيقة واحدة', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'دقيقة واحدة', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), 'دقيقتان', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '٤٤ دقيقة', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ساعة واحدة', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ساعة واحدة', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), 'ساعتان', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '٥ ساعات', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '٢١ ساعة', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'يوم واحد', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'يوم واحد', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), 'يومان', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'يوم واحد', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '٥ أيام', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '٢٥ يومًا', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'شهر واحد', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'شهر واحد', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'شهر واحد', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), 'شهران', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), 'شهران', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '٣ أشهر', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'شهر واحد', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '٥ أشهر', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'عام واحد', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), 'عامان', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'عام واحد', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '٥ أعوام', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'بعد ٣٠ ثانية', 'prefix'); + assert.equal(moment(0).from(30000), 'منذ ٣٠ ثانية', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'منذ ثانية واحدة', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'بعد ٣٠ ثانية', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'بعد ٥ أيام', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'اليوم عند الساعة ٠٢:٠٠', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'اليوم عند الساعة ٠٢:٢٥', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'اليوم عند الساعة ٠٣:٠٠', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'غدًا عند الساعة ٠٢:٠٠', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'اليوم عند الساعة ٠١:٠٠', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'أمس عند الساعة ٠٢:٠٠', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [عند الساعة] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [عند الساعة] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [عند الساعة] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [عند الساعة] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [عند الساعة] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [عند الساعة] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 31]).week(), 1, 'Dec 31 2011 should be week 1'); + assert.equal(moment([2012, 0, 6]).week(), 1, 'Jan 6 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 2, 'Jan 7 2012 should be week 2'); + assert.equal(moment([2012, 0, 13]).week(), 2, 'Jan 13 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 3, 'Jan 14 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 30]).week(), 1, 'Dec 30 2006 should be week 1'); + assert.equal(moment([2007, 0, 5]).week(), 1, 'Jan 5 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 2, 'Jan 6 2007 should be week 2'); + assert.equal(moment([2007, 0, 12]).week(), 2, 'Jan 12 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 3, 'Jan 13 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 1, 'Dec 29 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 4]).week(), 1, 'Jan 4 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 2, 'Jan 5 2008 should be week 2'); + assert.equal(moment([2008, 0, 11]).week(), 2, 'Jan 11 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 3, 'Jan 12 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 28]).week(), 1, 'Dec 28 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 3]).week(), 1, 'Jan 3 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 2, 'Jan 4 2003 should be week 2'); + assert.equal(moment([2003, 0, 10]).week(), 2, 'Jan 10 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 3, 'Jan 11 2003 should be week 3'); + + assert.equal(moment('2003 1 6', 'gggg w d').format('YYYY-MM-DD'), '٢٠٠٢-١٢-٢٨', 'Week 1 of 2003 should be Dec 28 2002'); + assert.equal(moment('2003 1 0', 'gggg w e').format('YYYY-MM-DD'), '٢٠٠٢-١٢-٢٨', 'Week 1 of 2003 should be Dec 28 2002'); + assert.equal(moment('2003 1 6', 'gggg w d').format('gggg w d'), '٢٠٠٣ ١ ٦', 'Saturday of week 1 of 2003 parsed should be formatted as 2003 1 6'); + assert.equal(moment('2003 1 0', 'gggg w e').format('gggg w e'), '٢٠٠٣ ١ ٠', '1st day of week 1 of 2003 parsed should be formatted as 2003 1 0'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 27]).week(), 1, 'Dec 27 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 2]).week(), 1, 'Jan 2 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 2, 'Jan 3 2009 should be week 2'); + assert.equal(moment([2009, 0, 9]).week(), 2, 'Jan 9 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 3, 'Jan 10 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 26]).week(), 1, 'Dec 26 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 2, 'Jan 2 2010 should be week 2'); + assert.equal(moment([2010, 0, 8]).week(), 2, 'Jan 8 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 3, 'Jan 9 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 7]).week(), 1, 'Jan 7 2011 should be week 1'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 14]).week(), 2, 'Jan 14 2011 should be week 2'); + assert.equal(moment([2011, 0, 15]).week(), 3, 'Jan 15 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 31]).format('w ww wo'), '١ ٠١ ١', 'Dec 31 2011 should be week 1'); + assert.equal(moment([2012, 0, 6]).format('w ww wo'), '١ ٠١ ١', 'Jan 6 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '٢ ٠٢ ٢', 'Jan 7 2012 should be week 2'); + assert.equal(moment([2012, 0, 13]).format('w ww wo'), '٢ ٠٢ ٢', 'Jan 13 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '٣ ٠٣ ٣', 'Jan 14 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + + test('no leading zeros in long date formats', function (assert) { + var i, j, longDateStr, shortDateStr; + for (i = 1; i <= 9; ++i) { + for (j = 1; j <= 9; ++j) { + longDateStr = moment([2014, i, j]).format('L'); + shortDateStr = moment([2014, i, j]).format('l'); + assert.equal(longDateStr, shortDateStr, 'should not have leading zeros in month or day'); + } + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('az'); + + test('parse', function (assert) { + var tests = 'yanvar yan_fevral fev_mart mar_Aprel apr_may may_iyun iyn_iyul iyl_Avqust avq_sentyabr sen_oktyabr okt_noyabr noy_dekabr dek'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, D MMMM YYYY, HH:mm:ss', 'Bazar, 14 fevral 2010, 15:25:50'], + ['ddd, A h', 'Baz, gündüz 3'], + ['M Mo MM MMMM MMM', '2 2-nci 02 fevral fev'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14-üncü 14'], + ['d do dddd ddd dd', '0 0-ıncı Bazar Baz Bz'], + ['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', 'gündüz gündüz'], + ['[ilin] DDDo [günü]', 'ilin 45-inci günü'], + ['LT', '15:25'], + ['LTS', '15:25:50'], + ['L', '14.02.2010'], + ['LL', '14 fevral 2010'], + ['LLL', '14 fevral 2010 15:25'], + ['LLLL', 'Bazar, 14 fevral 2010 15:25'], + ['l', '14.2.2010'], + ['ll', '14 fev 2010'], + ['lll', '14 fev 2010 15:25'], + ['llll', 'Baz, 14 fev 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; + + for (i = 0; i < a.length; i++) { + assert.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]); + assert.equal(DDDoDt.add(DDDo[i][0], 'days').format('DDDo'), DDDo[i][1], DDDo[i][0] + ' ---> ' + DDDo[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1-inci', '1st'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2-nci', '2nd'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3-üncü', '3rd'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4-üncü', '4th'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5-inci', '5th'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6-ncı', '6th'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7-nci', '7th'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8-inci', '8th'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9-uncu', '9th'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10-uncu', '10th'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11-inci', '11th'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12-nci', '12th'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13-üncü', '13th'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14-üncü', '14th'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15-inci', '15th'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16-ncı', '16th'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17-nci', '17th'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18-inci', '18th'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19-uncu', '19th'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20-nci', '20th'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21-inci', '21th'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22-nci', '22th'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23-üncü', '23th'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24-üncü', '24th'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25-inci', '25th'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26-ncı', '26th'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27-nci', '27th'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28-inci', '28th'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29-uncu', '29th'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30-uncu', '30th'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31-inci', '31st'); + }); + + test('format month', function (assert) { + var expected = 'yanvar yan_fevral fev_mart mar_aprel apr_may may_iyun iyn_iyul iyl_avqust avq_sentyabr sen_oktyabr okt_noyabr noy_dekabr dek'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Bazar Baz Bz_Bazar ertəsi BzE BE_Çərşənbə axşamı ÇAx ÇA_Çərşənbə Çər Çə_Cümə axşamı CAx CA_Cümə Cüm Cü_Şənbə Şən Şə'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'birneçə saniyyə', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'bir dəqiqə', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'bir dəqiqə', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 dəqiqə', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 dəqiqə', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'bir saat', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'bir saat', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 saat', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 saat', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 saat', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'bir gün', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'bir gün', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 gün', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'bir gün', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 gün', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 gün', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'bir ay', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'bir ay', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 ay', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 ay', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 ay', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'bir ay', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 ay', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'bir il', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 il', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'bir il', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 il', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'birneçə saniyyə sonra', 'prefix'); + assert.equal(moment(0).from(30000), 'birneçə saniyyə əvvəl', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'birneçə saniyyə əvvəl', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'birneçə saniyyə sonra', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), '5 gün sonra', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'bugün saat 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'bugün saat 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'bugün saat 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'sabah saat 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'bugün saat 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'dünən 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('[gələn həftə] dddd [saat] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[gələn həftə] dddd [saat] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[gələn həftə] dddd [saat] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[keçən həftə] dddd [saat] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[keçən həftə] dddd [saat] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[keçən həftə] dddd [saat] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-inci', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-inci', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2-nci', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2-nci', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3-üncü', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('be'); + + test('parse', function (assert) { + var tests = 'студзень студ_люты лют_сакавік сак_красавік крас_травень трав_чэрвень чэрв_ліпень ліп_жнівень жнів_верасень вер_кастрычнік каст_лістапад ліст_снежань снеж'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, Do MMMM YYYY, HH:mm:ss', 'нядзеля, 14-га лютага 2010, 15: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', '7 7-ы 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'дня дня'], + ['DDDo [дзень года]', '45-ы дзень года'], + ['LT', '15:25'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format meridiem', function (assert) { + assert.equal(moment([2012, 11, 28, 0, 0]).format('A'), 'ночы', 'night'); + assert.equal(moment([2012, 11, 28, 3, 59]).format('A'), 'ночы', 'night'); + assert.equal(moment([2012, 11, 28, 4, 0]).format('A'), 'раніцы', 'morning'); + assert.equal(moment([2012, 11, 28, 11, 59]).format('A'), 'раніцы', 'morning'); + assert.equal(moment([2012, 11, 28, 12, 0]).format('A'), 'дня', 'afternoon'); + assert.equal(moment([2012, 11, 28, 16, 59]).format('A'), 'дня', 'afternoon'); + assert.equal(moment([2012, 11, 28, 17, 0]).format('A'), 'вечара', 'evening'); + assert.equal(moment([2012, 11, 28, 23, 59]).format('A'), 'вечара', 'evening'); + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1-ы', '1-ы'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2-і', '2-і'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3-і', '3-і'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4-ы', '4-ы'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5-ы', '5-ы'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6-ы', '6-ы'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7-ы', '7-ы'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8-ы', '8-ы'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9-ы', '9-ы'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10-ы', '10-ы'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11-ы', '11-ы'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12-ы', '12-ы'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13-ы', '13-ы'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14-ы', '14-ы'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15-ы', '15-ы'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16-ы', '16-ы'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17-ы', '17-ы'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18-ы', '18-ы'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19-ы', '19-ы'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20-ы', '20-ы'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21-ы', '21-ы'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22-і', '22-і'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23-і', '23-і'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24-ы', '24-ы'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25-ы', '25-ы'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26-ы', '26-ы'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27-ы', '27-ы'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28-ы', '28-ы'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29-ы', '29-ы'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30-ы', '30-ы'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31-ы', '31-ы'); + }); + + test('format month', function (assert) { + var expected = 'студзень студ_люты лют_сакавік сак_красавік крас_травень трав_чэрвень чэрв_ліпень ліп_жнівень жнів_верасень вер_кастрычнік каст_лістапад ліст_снежань снеж'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format month case', function (assert) { + var months = { + 'nominative': 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_'), + 'accusative': 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_') + }, i; + for (i = 0; i < 12; i++) { + assert.equal(moment([2011, i, 1]).format('D MMMM'), '1 ' + months.accusative[i], '1 ' + months.accusative[i]); + assert.equal(moment([2011, i, 1]).format('MMMM'), months.nominative[i], '1 ' + months.nominative[i]); + } + }); + + test('format month case with escaped symbols', function (assert) { + var months = { + 'nominative': 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_'), + 'accusative': 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_') + }, i; + for (i = 0; i < 12; i++) { + assert.equal(moment([2013, i, 1]).format('D[] MMMM'), '1 ' + months.accusative[i], '1 ' + months.accusative[i]); + assert.equal(moment([2013, i, 1]).format('[<i>]D[</i>] [<b>]MMMM[</b>]'), '<i>1</i> <b>' + months.accusative[i] + '</b>', '1 <b>' + months.accusative[i] + '</b>'); + assert.equal(moment([2013, i, 1]).format('D[-ы дзень] MMMM'), '1-ы дзень ' + months.accusative[i], '1-ы дзень ' + months.accusative[i]); + assert.equal(moment([2013, i, 1]).format('D, MMMM'), '1, ' + months.nominative[i], '1, ' + months.nominative[i]); + } + }); + + test('format week', function (assert) { + var expected = 'нядзеля нд нд_панядзелак пн пн_аўторак ат ат_серада ср ср_чацвер чц чц_пятніца пт пт_субота сб сб'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'некалькі секунд', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'хвіліна', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'хвіліна', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 хвіліны', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 31}), true), '31 хвіліна', '31 minutes = 31 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 хвіліны', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'гадзіна', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'гадзіна', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 гадзіны', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 гадзін', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 гадзіна', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'дзень', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'дзень', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 дні', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'дзень', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 дзён', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 11}), true), '11 дзён', '11 days = 11 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 21}), true), '21 дзень', '21 days = 21 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 дзён', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'месяц', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'месяц', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'месяц', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 месяцы', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 месяцы', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 месяцы', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'месяц', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 месяцаў', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'год', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 гады', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'год', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 гадоў', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'праз некалькі секунд', 'prefix'); + assert.equal(moment(0).from(30000), 'некалькі секунд таму', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'праз некалькі секунд', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'праз 5 дзён', 'in 5 days'); + assert.equal(moment().add({m: 31}).fromNow(), 'праз 31 хвіліну', 'in 31 minutes = in 31 minutes'); + assert.equal(moment().subtract({m: 31}).fromNow(), '31 хвіліну таму', '31 minutes ago = 31 minutes ago'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Сёння ў 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Сёння ў 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Сёння ў 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Заўтра ў 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Сёння ў 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Учора ў 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + function makeFormat(d) { + return '[У] dddd [ў] LT'; + } + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + case 3: + case 5: + case 6: + return '[У мінулую] dddd [ў] LT'; + case 1: + case 2: + case 4: + return '[У мінулы] dddd [ў] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-ы', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-ы', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2-і', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2-і', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3-і', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('bg'); + + test('parse', function (assert) { + var tests = 'януари янр_февруари фев_март мар_април апр_май май_юни юни_юли юли_август авг_септември сеп_октомври окт_ноември ное_декември дек'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, H: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'], + ['[the] DDDo [day of the year]', 'the 45-ти day of the year'], + ['LT', '15:25'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1-ви', '1-ви'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2-ри', '2-ри'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3-ти', '3-ти'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4-ти', '4-ти'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5-ти', '5-ти'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6-ти', '6-ти'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7-ми', '7-ми'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8-ми', '8-ми'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9-ти', '9-ти'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10-ти', '10-ти'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11-ти', '11-ти'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12-ти', '12-ти'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13-ти', '13-ти'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14-ти', '14-ти'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15-ти', '15-ти'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16-ти', '16-ти'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17-ти', '17-ти'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18-ти', '18-ти'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19-ти', '19-ти'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20-ти', '20-ти'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21-ви', '21-ви'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22-ри', '22-ри'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23-ти', '23-ти'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24-ти', '24-ти'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25-ти', '25-ти'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26-ти', '26-ти'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27-ми', '27-ми'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28-ми', '28-ми'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29-ти', '29-ти'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30-ти', '30-ти'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31-ви', '31-ви'); + }); + + test('format month', function (assert) { + var expected = 'януари янр_февруари фев_март мар_април апр_май май_юни юни_юли юли_август авг_септември сеп_октомври окт_ноември ное_декември дек'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'неделя нед нд_понеделник пон пн_вторник вто вт_сряда сря ср_четвъртък чет чт_петък пет пт_събота съб сб'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'няколко секунди', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'минута', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'минута', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 минути', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 минути', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'час', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'час', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 часа', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 часа', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 часа', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'ден', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'ден', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 дни', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'ден', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 дни', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 дни', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'месец', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'месец', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'месец', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 месеца', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 месеца', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 месеца', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'месец', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 месеца', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'година', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 години', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'година', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 години', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'след няколко секунди', 'prefix'); + assert.equal(moment(0).from(30000), 'преди няколко секунди', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'преди няколко секунди', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'след няколко секунди', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'след 5 дни', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Днес в 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Днес в 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Днес в 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Утре в 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Днес в 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Вчера в 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [в] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [в] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [в] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, 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}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-ви', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-ви', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2-ри', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2-ри', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3-ти', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('bn'); + + test('parse', function (assert) { + var tests = 'জানুয়ারী জানু_ফেবুয়ারী ফেব_মার্চ মার্চ_এপ্রিল এপর_মে মে_জুন জুন_জুলাই জুল_অগাস্ট অগ_সেপ্টেম্বর সেপ্ট_অক্টোবর অক্টো_নভেম্বর নভ_ডিসেম্বর ডিসেম্'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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', 'দুপুর দুপুর'], + ['LT', 'দুপুর ৩:২৫ সময়'], + ['LTS', 'দুপুর ৩:২৫:৫০ সময়'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '১', '১'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '২', '২'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '৩', '৩'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '৪', '৪'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '৫', '৫'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '৬', '৬'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '৭', '৭'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '৮', '৮'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '৯', '৯'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '১০', '১০'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '১১', '১১'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '১২', '১২'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '১৩', '১৩'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '১৪', '১৪'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '১৫', '১৫'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '১৬', '১৬'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '১৭', '১৭'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '১৮', '১৮'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '১৯', '১৯'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '২০', '২০'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '২১', '২১'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '২২', '২২'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '২৩', '২৩'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '২৪', '২৪'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '২৫', '২৫'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '২৬', '২৬'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '২৭', '২৭'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '২৮', '२৮'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '২৯', '২৯'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '৩০', '৩০'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '৩১', '৩১'); + }); + + test('format month', function (assert) { + var expected = 'জানুয়ারী জানু_ফেবুয়ারী ফেব_মার্চ মার্চ_এপ্রিল এপর_মে মে_জুন জুন_জুলাই জুল_অগাস্ট অগ_সেপ্টেম্বর সেপ্ট_অক্টোবর অক্টো_নভেম্বর নভ_ডিসেম্বর ডিসেম্'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'রবিবার রবি রব_সোমবার সোম সম_মঙ্গলবার মঙ্গল মঙ্গ_বুধবার বুধ বু_বৃহস্পত্তিবার বৃহস্পত্তি ব্রিহ_শুক্রুবার শুক্রু শু_শনিবার শনি শনি'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'কএক সেকেন্ড', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'এক মিনিট', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'এক মিনিট', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '২ মিনিট', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '৪৪ মিনিট', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'এক ঘন্টা', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'এক ঘন্টা', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '২ ঘন্টা', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '৫ ঘন্টা', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '২১ ঘন্টা', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'এক দিন', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'এক দিন', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '২ দিন', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'এক দিন', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '৫ দিন', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '২৫ দিন', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'এক মাস', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'এক মাস', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '২ মাস', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '২ মাস', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '৩ মাস', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'এক মাস', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '৫ মাস', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'এক বছর', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '২ বছর', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'এক বছর', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '৫ বছর', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'কএক সেকেন্ড পরে', 'prefix'); + assert.equal(moment(0).from(30000), 'কএক সেকেন্ড আগে', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'কএক সেকেন্ড আগে', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'কএক সেকেন্ড পরে', 'কএক সেকেন্ড পরে'); + assert.equal(moment().add({d: 5}).fromNow(), '৫ দিন পরে', '৫ দিন পরে'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'আজ রাত ২:০০ সময়', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'আজ রাত ২:২৫ সময়', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 3}).calendar(), 'আজ শকাল ৫:০০ সময়', 'Now plus 3 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'আগামীকাল রাত ২:০০ সময়', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'আজ রাত ১:০০ সময়', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'গতকাল রাত ২:০০ সময়', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd[,] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd[,] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd[,] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[গত] dddd[,] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[গত] dddd[,] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[গত] dddd[,] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('meridiem', function (assert) { + assert.equal(moment([2011, 2, 23, 2, 30]).format('a'), 'রাত', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('a'), 'শকাল', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('a'), 'দুপুর', 'during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('a'), 'বিকেল', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('a'), 'বিকেল', 'late evening'); + assert.equal(moment([2011, 2, 23, 21, 20]).format('a'), 'রাত', 'night'); + + assert.equal(moment([2011, 2, 23, 2, 30]).format('A'), 'রাত', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('A'), 'শকাল', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('A'), 'দুপুর', ' during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('A'), 'বিকেল', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('A'), 'বিকেল', 'late evening'); + assert.equal(moment([2011, 2, 23, 21, 20]).format('A'), 'রাত', 'night'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '১ ০১ ১', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '১ ০১ ১', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '২ ০২ ২', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '২ ০২ ২', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '৩ ০৩ ৩', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('bo'); + + test('parse', function (assert) { + var tests = 'ཟླ་བ་དང་པོ ཟླ་བ་དང་པོ._ཟླ་བ་གཉིས་པ ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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', 'ཉིན་གུང ཉིན་གུང'], + ['LT', 'ཉིན་གུང ༣:༢༥'], + ['LTS', 'ཉིན་གུང ༣:༢༥:༥༠'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '༡', '༡'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '༢', '༢'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '༣', '༣'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '༤', '༤'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '༥', '༥'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '༦', '༦'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '༧', '༧'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '༨', '༨'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '༩', '༩'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '༡༠', '༡༠'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '༡༡', '༡༡'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '༡༢', '༡༢'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '༡༣', '༡༣'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '༡༤', '༡༤'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '༡༥', '༡༥'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '༡༦', '༡༦'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '༡༧', '༡༧'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '༡༨', '༡༨'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '༡༩', '༡༩'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '༢༠', '༢༠'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '༢༡', '༢༡'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '༢༢', '༢༢'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '༢༣', '༢༣'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '༢༤', '༢༤'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '༢༥', '༢༥'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '༢༦', '༢༦'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '༢༧', '༢༧'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '༢༨', '༢༨'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '༢༩', '༢༩'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '༣༠', '༣༠'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '༣༡', '༣༡'); + }); + + test('format month', function (assert) { + var expected = 'ཟླ་བ་དང་པོ ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'གཟའ་ཉི་མ་ ཉི་མ་ ཉི་མ་_གཟའ་ཟླ་བ་ ཟླ་བ་ ཟླ་བ་_གཟའ་མིག་དམར་ མིག་དམར་ མིག་དམར་_གཟའ་ལྷག་པ་ ལྷག་པ་ ལྷག་པ་_གཟའ་ཕུར་བུ ཕུར་བུ ཕུར་བུ_གཟའ་པ་སངས་ པ་སངས་ པ་སངས་_གཟའ་སྤེན་པ་ སྤེན་པ་ སྤེན་པ་'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'ལམ་སང', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'སྐར་མ་གཅིག', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'སྐར་མ་གཅིག', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '༢ སྐར་མ', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '༤༤ སྐར་མ', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ཆུ་ཚོད་གཅིག', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ཆུ་ཚོད་གཅིག', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '༢ ཆུ་ཚོད', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '༥ ཆུ་ཚོད', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '༢༡ ཆུ་ཚོད', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'ཉིན་གཅིག', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'ཉིན་གཅིག', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '༢ ཉིན་', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'ཉིན་གཅིག', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '༥ ཉིན་', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '༢༥ ཉིན་', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ཟླ་བ་གཅིག', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ཟླ་བ་གཅིག', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ཟླ་བ་གཅིག', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '༢ ཟླ་བ', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '༢ ཟླ་བ', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '༣ ཟླ་བ', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ཟླ་བ་གཅིག', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '༥ ཟླ་བ', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ལོ་གཅིག', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '༢ ལོ', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ལོ་གཅིག', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '༥ ལོ', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'ལམ་སང ལ་', 'prefix'); + assert.equal(moment(0).from(30000), 'ལམ་སང སྔན་ལ', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'ལམ་སང སྔན་ལ', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'ལམ་སང ལ་', 'ལམ་སང ལ་'); + assert.equal(moment().add({d: 5}).fromNow(), '༥ ཉིན་ ལ་', '༥ ཉིན་ ལ་'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'དི་རིང མཚན་མོ ༢:༠༠', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'དི་རིང མཚན་མོ ༢:༢༥', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 3}).calendar(), 'དི་རིང ཞོགས་ཀས ༥:༠༠', 'Now plus 3 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'སང་ཉིན མཚན་མོ ༢:༠༠', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'དི་རིང མཚན་མོ ༡:༠༠', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'ཁ་སང མཚན་མོ ༢:༠༠', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('[བདུན་ཕྲག་རྗེས་མ][,] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[བདུན་ཕྲག་རྗེས་མ][,] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[བདུན་ཕྲག་རྗེས་མ][,] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[བདུན་ཕྲག་མཐའ་མ] dddd[,] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[བདུན་ཕྲག་མཐའ་མ] dddd[,] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[བདུན་ཕྲག་མཐའ་མ] dddd[,] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('meridiem', function (assert) { + assert.equal(moment([2011, 2, 23, 2, 30]).format('a'), 'མཚན་མོ', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('a'), 'ཞོགས་ཀས', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('a'), 'ཉིན་གུང', 'during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('a'), 'དགོང་དག', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('a'), 'དགོང་དག', 'late evening'); + assert.equal(moment([2011, 2, 23, 21, 20]).format('a'), 'མཚན་མོ', 'night'); + + assert.equal(moment([2011, 2, 23, 2, 30]).format('A'), 'མཚན་མོ', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('A'), 'ཞོགས་ཀས', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('A'), 'ཉིན་གུང', ' during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('A'), 'དགོང་དག', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('A'), 'དགོང་དག', 'late evening'); + assert.equal(moment([2011, 2, 23, 21, 20]).format('A'), 'མཚན་མོ', 'night'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '༡ ༠༡ ༡', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '༡ ༠༡ ༡', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '༢ ༠༢ ༢', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '༢ ༠༢ ༢', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '༣ ༠༣ ༣', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('br'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + moment.locale('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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + moment.locale('br'); + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1añ', '1añ'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2vet', '2vet'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3vet', '3vet'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4vet', '4vet'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5vet', '5vet'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6vet', '6vet'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7vet', '7vet'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8vet', '8vet'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9vet', '9vet'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10vet', '10vet'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11vet', '11vet'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12vet', '12vet'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13vet', '13vet'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14vet', '14vet'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15vet', '15vet'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16vet', '16vet'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17vet', '17vet'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18vet', '18vet'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19vet', '19vet'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20vet', '20vet'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21vet', '21vet'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22vet', '22vet'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23vet', '23vet'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24vet', '24vet'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25vet', '25vet'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26vet', '26vet'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27vet', '27vet'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28vet', '28vet'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29vet', '29vet'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30vet', '30vet'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31vet', '31vet'); + }); + + test('format month', function (assert) { + moment.locale('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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + moment.locale('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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + moment.locale('br'); + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'un nebeud segondennoù', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'ur vunutenn', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'ur vunutenn', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 vunutenn', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 munutenn', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'un eur', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'un eur', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 eur', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 eur', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 eur', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'un devezh', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'un devezh', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 zevezh', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'un devezh', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 devezh', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 devezh', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ur miz', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ur miz', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ur miz', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 viz', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 viz', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 miz', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ur miz', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 miz', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ur bloaz', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 vloaz', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ur bloaz', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 bloaz', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + moment.locale('br'); + assert.equal(moment(30000).from(0), 'a-benn un nebeud segondennoù', 'prefix'); + assert.equal(moment(0).from(30000), 'un nebeud segondennoù \'zo', 'suffix'); + }); + + test('now from now', function (assert) { + moment.locale('br'); + assert.equal(moment().fromNow(), 'un nebeud segondennoù \'zo', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + moment.locale('br'); + assert.equal(moment().add({s: 30}).fromNow(), 'a-benn un nebeud segondennoù', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'a-benn 5 devezh', 'in 5 days'); + }); + + test('calendar day', function (assert) { + moment.locale('br'); + + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Hiziv da 2e00 AM', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Hiziv da 2e25 AM', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Hiziv da 3e00 AM', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Warc\'hoazh da 2e00 AM', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Hiziv da 1e00 AM', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Dec\'h da 2e00 AM', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + moment.locale('br'); + + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [da] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [da] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [da] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + moment.locale('br'); + + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [paset da] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [paset da] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [paset da] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + moment.locale('br'); + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('special mutations for years', function (assert) { + moment.locale('br'); + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ur bloaz', 'mutation 1 year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 2}), true), '2 vloaz', 'mutation 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 3}), true), '3 bloaz', 'mutation 3 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 4}), true), '4 bloaz', 'mutation 4 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 bloaz', 'mutation 5 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 9}), true), '9 bloaz', 'mutation 9 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 10}), true), '10 vloaz', 'mutation 10 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 21}), true), '21 bloaz', 'mutation 21 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 22}), true), '22 vloaz', 'mutation 22 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 133}), true), '133 bloaz', 'mutation 133 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 148}), true), '148 vloaz', 'mutation 148 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 261}), true), '261 bloaz', 'mutation 261 years'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('bs'); + + test('parse', function (assert) { + var tests = 'januar jan._februar feb._mart mar._april apr._maj maj._juni jun._juli jul._august aug._septembar sep._oktobar okt._novembar nov._decembar dec.'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, Do MMMM YYYY, h:mm:ss a', 'nedjelja, 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. nedjelja 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'], + ['LTS', '15:25:50'], + ['L', '14. 02. 2010'], + ['LL', '14. februar 2010'], + ['LLL', '14. februar 2010 15:25'], + ['LLLL', 'nedjelja, 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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + var expected = 'januar jan._februar feb._mart mar._april apr._maj maj._juni jun._juli jul._august aug._septembar sep._oktobar okt._novembar nov._decembar dec.'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'nedjelja ned. ne_ponedjeljak pon. po_utorak uto. ut_srijeda sri. sr_četvrtak čet. če_petak pet. pe_subota sub. su'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'par sekundi', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'jedna minuta', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'jedna minuta', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minute', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuta', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'jedan sat', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'jedan sat', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 sata', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 sati', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 sati', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'dan', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'dan', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dana', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'dan', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dana', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dana', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'mjesec', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'mjesec', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'mjesec', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mjeseca', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mjeseca', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mjeseca', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'mjesec', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mjeseci', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'godinu', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 godine', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'godinu', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 godina', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'za par sekundi', 'prefix'); + assert.equal(moment(0).from(30000), 'prije par sekundi', 'prefix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'prije par sekundi', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'za par sekundi', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'za 5 dana', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'danas u 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'danas u 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'danas u 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'sutra u 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'danas u 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'jučer u 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1.', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1.', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2.', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2.', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3.', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ca'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, Do MMMM YYYY, h:mm:ss a', 'diumenge, 14è febrer 2010, 3:25:50 pm'], + ['ddd, hA', 'dg., 3PM'], + ['M Mo MM MMMM MMM', '2 2n 02 febrer febr.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14è 14'], + ['d do dddd ddd dd', '0 0è diumenge dg. Dg'], + ['DDD DDDo DDDD', '45 45è 045'], + ['w wo ww', '6 6a 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'], + ['LTS', '15:25:50'], + ['L', '14/02/2010'], + ['LL', '14 febrer 2010'], + ['LLL', '14 febrer 2010 15:25'], + ['LLLL', 'diumenge 14 febrer 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 febr. 2010'], + ['lll', '14 febr. 2010 15:25'], + ['llll', 'dg. 14 febr. 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1r', '1r'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2n', '2n'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3r', '3r'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4t', '4t'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5è', '5è'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6è', '6è'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7è', '7è'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8è', '8è'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9è', '9è'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10è', '10è'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11è', '11è'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12è', '12è'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13è', '13è'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14è', '14è'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15è', '15è'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16è', '16è'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17è', '17è'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18è', '18è'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19è', '19è'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20è', '20è'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21è', '21è'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22è', '22è'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23è', '23è'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24è', '24è'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25è', '25è'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26è', '26è'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27è', '27è'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28è', '28è'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29è', '29è'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30è', '30è'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31è', '31è'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'diumenge dg. Dg_dilluns dl. Dl_dimarts dt. Dt_dimecres dc. Dc_dijous dj. Dj_divendres dv. Dv_dissabte ds. Ds'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'uns segons', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'un minut', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'un minut', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuts', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuts', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'una hora', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'una hora', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 hores', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 hores', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 hores', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'un dia', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'un dia', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dies', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'un dia', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dies', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dies', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'un mes', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'un mes', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'un mes', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mesos', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mesos', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mesos', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'un mes', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mesos', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'un any', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 anys', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'un any', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 anys', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'en uns segons', 'prefix'); + assert.equal(moment(0).from(30000), 'fa uns segons', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'fa uns segons', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'en uns segons', 'en uns segons'); + assert.equal(moment().add({d: 5}).fromNow(), 'en 5 dies', 'en 5 dies'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'avui a les 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'avui a les 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'avui a les 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'demà a les 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).add({d: 1, h : -1}).calendar(), 'demà a la 1:00', 'tomorrow minus 1 hour'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'avui a la 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'ahir a les 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.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); + assert.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); + assert.equal(m.calendar(), m.format('dddd [a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.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); + assert.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); + assert.equal(m.calendar(), m.format('[el] dddd [passat a ' + ((m.hours() !== 1) ? 'les' : 'la') + '] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52a', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1a', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1a', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2a', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2a', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('cs'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, monthIndex) { + assert.equal(moment(input, mmm).month(), monthIndex, input + ' should be month ' + (monthIndex + 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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'pár sekund', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'minuta', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'minuta', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuty', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minut', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'hodina', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'hodina', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 hodiny', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 hodin', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 hodin', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'den', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'den', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dny', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'den', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dní', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dní', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'měsíc', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'měsíc', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'měsíc', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 měsíce', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 měsíce', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 měsíce', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'měsíc', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 měsíců', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'rok', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 roky', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'rok', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 let', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'za pár sekund', 'prefix'); + assert.equal(moment(0).from(30000), 'před pár sekundami', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'před pár sekundami', 'now from now should display as in the past'); + }); + + test('fromNow (future)', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'za pár sekund', 'in a few seconds'); + assert.equal(moment().add({m: 1}).fromNow(), 'za minutu', 'in a minute'); + assert.equal(moment().add({m: 3}).fromNow(), 'za 3 minuty', 'in 3 minutes'); + assert.equal(moment().add({m: 10}).fromNow(), 'za 10 minut', 'in 10 minutes'); + assert.equal(moment().add({h: 1}).fromNow(), 'za hodinu', 'in an hour'); + assert.equal(moment().add({h: 3}).fromNow(), 'za 3 hodiny', 'in 3 hours'); + assert.equal(moment().add({h: 10}).fromNow(), 'za 10 hodin', 'in 10 hours'); + assert.equal(moment().add({d: 1}).fromNow(), 'za den', 'in a day'); + assert.equal(moment().add({d: 3}).fromNow(), 'za 3 dny', 'in 3 days'); + assert.equal(moment().add({d: 10}).fromNow(), 'za 10 dní', 'in 10 days'); + assert.equal(moment().add({M: 1}).fromNow(), 'za měsíc', 'in a month'); + assert.equal(moment().add({M: 3}).fromNow(), 'za 3 měsíce', 'in 3 months'); + assert.equal(moment().add({M: 10}).fromNow(), 'za 10 měsíců', 'in 10 months'); + assert.equal(moment().add({y: 1}).fromNow(), 'za rok', 'in a year'); + assert.equal(moment().add({y: 3}).fromNow(), 'za 3 roky', 'in 3 years'); + assert.equal(moment().add({y: 10}).fromNow(), 'za 10 let', 'in 10 years'); + }); + + test('fromNow (past)', function (assert) { + assert.equal(moment().subtract({s: 30}).fromNow(), 'před pár sekundami', 'a few seconds ago'); + assert.equal(moment().subtract({m: 1}).fromNow(), 'před minutou', 'a minute ago'); + assert.equal(moment().subtract({m: 3}).fromNow(), 'před 3 minutami', '3 minutes ago'); + assert.equal(moment().subtract({m: 10}).fromNow(), 'před 10 minutami', '10 minutes ago'); + assert.equal(moment().subtract({h: 1}).fromNow(), 'před hodinou', 'an hour ago'); + assert.equal(moment().subtract({h: 3}).fromNow(), 'před 3 hodinami', '3 hours ago'); + assert.equal(moment().subtract({h: 10}).fromNow(), 'před 10 hodinami', '10 hours ago'); + assert.equal(moment().subtract({d: 1}).fromNow(), 'před dnem', 'a day ago'); + assert.equal(moment().subtract({d: 3}).fromNow(), 'před 3 dny', '3 days ago'); + assert.equal(moment().subtract({d: 10}).fromNow(), 'před 10 dny', '10 days ago'); + assert.equal(moment().subtract({M: 1}).fromNow(), 'před měsícem', 'a month ago'); + assert.equal(moment().subtract({M: 3}).fromNow(), 'před 3 měsíci', '3 months ago'); + assert.equal(moment().subtract({M: 10}).fromNow(), 'před 10 měsíci', '10 months ago'); + assert.equal(moment().subtract({y: 1}).fromNow(), 'před rokem', 'a year ago'); + assert.equal(moment().subtract({y: 3}).fromNow(), 'před 3 lety', '3 years ago'); + assert.equal(moment().subtract({y: 10}).fromNow(), 'před 10 lety', '10 years ago'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'dnes v 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'dnes v 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'dnes v 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'zítra v 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'dnes v 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'včera v 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m, nextDay; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + 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; + } + assert.equal(m.calendar(), m.format('[' + nextDay + '] [v] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[' + nextDay + '] [v] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[' + nextDay + '] [v] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m, lastDay; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + 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; + } + assert.equal(m.calendar(), m.format('[' + lastDay + '] [v] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[' + lastDay + '] [v] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[' + lastDay + '] [v] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('humanize duration', function (assert) { + assert.equal(moment.duration(1, 'minutes').humanize(), 'minuta', 'a minute (future)'); + assert.equal(moment.duration(1, 'minutes').humanize(true), 'za minutu', 'in a minute'); + assert.equal(moment.duration(-1, 'minutes').humanize(), 'minuta', 'a minute (past)'); + assert.equal(moment.duration(-1, 'minutes').humanize(true), 'před minutou', 'a minute ago'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('cv'); + + test('parse', function (assert) { + var tests = 'кӑрлач кӑр_нарӑс нар_пуш пуш_ака ака_май май_ҫӗртме ҫӗр_утӑ утӑ_ҫурла ҫур_авӑн авн_юпа юпа_чӳк чӳк_раштав раш'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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-мӗш кунӗ'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1-мӗш', '1-мӗш'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2-мӗш', '2-мӗш'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3-мӗш', '3-мӗш'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4-мӗш', '4-мӗш'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5-мӗш', '5-мӗш'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6-мӗш', '6-мӗш'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7-мӗш', '7-мӗш'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8-мӗш', '8-мӗш'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9-мӗш', '9-мӗш'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10-мӗш', '10-мӗш'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11-мӗш', '11-мӗш'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12-мӗш', '12-мӗш'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13-мӗш', '13-мӗш'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14-мӗш', '14-мӗш'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15-мӗш', '15-мӗш'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16-мӗш', '16-мӗш'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17-мӗш', '17-мӗш'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18-мӗш', '18-мӗш'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19-мӗш', '19-мӗш'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20-мӗш', '20-мӗш'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21-мӗш', '21-мӗш'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22-мӗш', '22-мӗш'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23-мӗш', '23-мӗш'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24-мӗш', '24-мӗш'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25-мӗш', '25-мӗш'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26-мӗш', '26-мӗш'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27-мӗш', '27-мӗш'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28-мӗш', '28-мӗш'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29-мӗш', '29-мӗш'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30-мӗш', '30-мӗш'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31-мӗш', '31-мӗш'); + }); + + test('format month', function (assert) { + var expected = 'кӑрлач кӑр_нарӑс нар_пуш пуш_ака ака_май май_ҫӗртме ҫӗр_утӑ утӑ_ҫурла ҫур_авӑн авн_юпа юпа_чӳк чӳк_раштав раш'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'вырсарникун выр вр_тунтикун тун тн_ытларикун ытл ыт_юнкун юн юн_кӗҫнерникун кӗҫ кҫ_эрнекун эрн эр_шӑматкун шӑм шм'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'пӗр-ик ҫеккунт', '44 sekunder = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'пӗр минут', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'пӗр минут', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 минут', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 минут', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'пӗр сехет', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'пӗр сехет', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 сехет', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 сехет', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 сехет', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'пӗр кун', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'пӗр кун', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 кун', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'пӗр кун', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 кун', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 кун', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'пӗр уйӑх', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'пӗр уйӑх', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'пӗр уйӑх', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 уйӑх', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 уйӑх', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 уйӑх', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'пӗр уйӑх', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 уйӑх', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'пӗр ҫул', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 ҫул', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'пӗр ҫул', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 ҫул', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'пӗр-ик ҫеккунтран', 'prefix'); + assert.equal(moment(0).from(30000), 'пӗр-ик ҫеккунт каялла', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'пӗр-ик ҫеккунт каялла', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'пӗр-ик ҫеккунтран', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), '5 кунран', 'in 5 days'); + assert.equal(moment().add({h: 2}).fromNow(), '2 сехетрен', 'in 2 hours, the right suffix!'); + assert.equal(moment().add({y: 3}).fromNow(), '3 ҫултан', 'in 3 years, the right suffix!'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + assert.equal(moment(a).calendar(), 'Паян 02:00 сехетре', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Паян 02:25 сехетре', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Паян 03:00 сехетре', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Ыран 02:00 сехетре', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Паян 01:00 сехетре', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Ӗнер 02:00 сехетре', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('[Ҫитес] dddd LT [сехетре]'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[Ҫитес] dddd LT [сехетре]'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[Ҫитес] dddd LT [сехетре]'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[Иртнӗ] dddd LT [сехетре]'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[Иртнӗ] dddd LT [сехетре]'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[Иртнӗ] dddd LT [сехетре]'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-мӗш', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-мӗш', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2-мӗш', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2-мӗш', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3-мӗш', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('cy'); + + test('parse', function (assert) { + var tests = 'Ionawr Ion_Chwefror Chwe_Mawrth Maw_Ebrill Ebr_Mai Mai_Mehefin Meh_Gorffennaf Gor_Awst Aws_Medi Med_Hydref Hyd_Tachwedd Tach_Rhagfyr Rhag'.split('_'), + i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Dydd Sul, Chwefror 14eg 2010, 3:25:50 pm'], + ['ddd, hA', 'Sul, 3PM'], + ['M Mo MM MMMM MMM', '2 2il 02 Chwefror Chwe'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14eg 14'], + ['d do dddd ddd dd', '0 0 Dydd Sul Sul Su'], + ['DDD DDDo DDDD', '45 45ain 045'], + ['w wo ww', '6 6ed 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 45ain day of the year'], + ['LTS', '15:25:50'], + ['L', '14/02/2010'], + ['LL', '14 Chwefror 2010'], + ['LLL', '14 Chwefror 2010 15:25'], + ['LLLL', 'Dydd Sul, 14 Chwefror 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 Chwe 2010'], + ['lll', '14 Chwe 2010 15:25'], + ['llll', 'Sul, 14 Chwe 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1af', '1af'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2il', '2il'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3ydd', '3ydd'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4ydd', '4ydd'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5ed', '5ed'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6ed', '6ed'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7ed', '7ed'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8fed', '8fed'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9fed', '9fed'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10fed', '10fed'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11eg', '11eg'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12fed', '12fed'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13eg', '13eg'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14eg', '14eg'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15fed', '15fed'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16eg', '16eg'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17eg', '17eg'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18fed', '18fed'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19eg', '19eg'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20fed', '20fed'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21ain', '21ain'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22ain', '22ain'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23ain', '23ain'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24ain', '24ain'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25ain', '25ain'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26ain', '26ain'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27ain', '27ain'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28ain', '28ain'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29ain', '29ain'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30ain', '30ain'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31ain', '31ain'); + }); + + test('format month', function (assert) { + var expected = 'Ionawr Ion_Chwefror Chwe_Mawrth Maw_Ebrill Ebr_Mai Mai_Mehefin Meh_Gorffennaf Gor_Awst Aws_Medi Med_Hydref Hyd_Tachwedd Tach_Rhagfyr Rhag'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Dydd Sul Sul Su_Dydd Llun Llun Ll_Dydd Mawrth Maw Ma_Dydd Mercher Mer Me_Dydd Iau Iau Ia_Dydd Gwener Gwe Gw_Dydd Sadwrn Sad Sa'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'ychydig eiliadau', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'munud', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'munud', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 munud', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 munud', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'awr', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'awr', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 awr', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 awr', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 awr', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'diwrnod', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'diwrnod', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 diwrnod', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'diwrnod', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 diwrnod', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 diwrnod', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'mis', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'mis', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'mis', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mis', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mis', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mis', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'mis', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mis', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'blwyddyn', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 flynedd', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'blwyddyn', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 flynedd', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'mewn ychydig eiliadau', 'prefix'); + assert.equal(moment(0).from(30000), 'ychydig eiliadau yn ôl', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'mewn ychydig eiliadau', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'mewn 5 diwrnod', 'in 5 days'); + }); + + test('same day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Heddiw am 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Heddiw am 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Heddiw am 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Yfory am 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Heddiw am 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Ddoe am 02:00', 'yesterday at the same time'); + }); + + test('same next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [am] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [am] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [am] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('same last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [diwethaf am] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [diwethaf am] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [diwethaf am] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('same all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52ain', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1af', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1af', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2il', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2il', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('da'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['L', '14/02/2010'], + ['LL', '14. februar 2010'], + ['LLL', '14. februar 2010 15:25'], + ['LLLL', 'søndag d. 14. februar 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14. feb 2010'], + ['lll', '14. feb 2010 15:25'], + ['llll', 'søn d. 14. feb 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'få sekunder', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'et minut', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'et minut', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutter', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutter', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'en time', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'en time', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 timer', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 timer', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 timer', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'en dag', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'en dag', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dage', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'en dag', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dage', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dage', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'en måned', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'en måned', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'en måned', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 måneder', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 måneder', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 måneder', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'en måned', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 måneder', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'et år', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 år', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'et år', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 år', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'om få sekunder', 'prefix'); + assert.equal(moment(0).from(30000), 'få sekunder siden', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'få sekunder siden', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'om få sekunder', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'om 5 dage', 'in 5 days'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('de-at'); + + test('parse', function (assert) { + var tests = 'Jänner Jän._Februar Febr._März Mrz._April Apr._Mai Mai_Juni Jun._Juli Jul._August Aug._September Sept._Oktober Okt._November Nov._Dezember Dez.'.split('_'), i; + + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['L', '14.02.2010'], + ['LL', '14. Februar 2010'], + ['LLL', '14. Februar 2010 15:25'], + ['LLLL', 'Sonntag, 14. Februar 2010 15:25'], + ['l', '14.2.2010'], + ['ll', '14. Febr. 2010'], + ['lll', '14. Febr. 2010 15:25'], + ['llll', 'So., 14. Febr. 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + var expected = 'Jänner Jän._Februar Febr._März Mrz._April Apr._Mai Mai_Juni Jun._Juli Jul._August Aug._September Sept._Oktober Okt._November Nov._Dezember Dez.'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Sonntag So. So_Montag Mo. Mo_Dienstag Di. Di_Mittwoch Mi. Mi_Donnerstag Do. Do_Freitag Fr. Fr_Samstag Sa. Sa'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'ein paar Sekunden', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'eine Minute', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'eine Minute', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 Minuten', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 Minuten', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'eine Stunde', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'eine Stunde', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 Stunden', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 Stunden', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 Stunden', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'ein Tag', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'ein Tag', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 Tage', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'ein Tag', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 Tage', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 Tage', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ein Monat', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ein Monat', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 Monate', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 Monate', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 Monate', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ein Monat', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 Monate', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ein Jahr', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 Jahre', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ein Jahr', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 Jahre', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'in ein paar Sekunden', 'prefix'); + assert.equal(moment(0).from(30000), 'vor ein paar Sekunden', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'in ein paar Sekunden', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'in 5 Tagen', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Heute um 02:00 Uhr', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Heute um 02:25 Uhr', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Heute um 03:00 Uhr', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Morgen um 02:00 Uhr', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Heute um 01:00 Uhr', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Gestern um 02:00 Uhr', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [um] LT [Uhr]'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [um] LT [Uhr]'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [um] LT [Uhr]'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[letzten] dddd [um] LT [Uhr]'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[letzten] dddd [um] LT [Uhr]'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[letzten] dddd [um] LT [Uhr]'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('de'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['L', '14.02.2010'], + ['LL', '14. Februar 2010'], + ['LLL', '14. Februar 2010 15:25'], + ['LLLL', 'Sonntag, 14. Februar 2010 15:25'], + ['l', '14.2.2010'], + ['ll', '14. Febr. 2010'], + ['lll', '14. Febr. 2010 15:25'], + ['llll', 'So., 14. Febr. 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Sonntag So. So_Montag Mo. Mo_Dienstag Di. Di_Mittwoch Mi. Mi_Donnerstag Do. Do_Freitag Fr. Fr_Samstag Sa. Sa'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'ein paar Sekunden', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'eine Minute', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'eine Minute', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 Minuten', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 Minuten', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'eine Stunde', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'eine Stunde', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 Stunden', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 Stunden', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 Stunden', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'ein Tag', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'ein Tag', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 Tage', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'ein Tag', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 Tage', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 Tage', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ein Monat', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ein Monat', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ein Monat', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 Monate', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 Monate', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 Monate', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ein Monat', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 Monate', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ein Jahr', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 Jahre', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ein Jahr', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 Jahre', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'in ein paar Sekunden', 'prefix'); + assert.equal(moment(0).from(30000), 'vor ein paar Sekunden', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'in ein paar Sekunden', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'in 5 Tagen', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Heute um 02:00 Uhr', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Heute um 02:25 Uhr', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Heute um 03:00 Uhr', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Morgen um 02:00 Uhr', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Heute um 01:00 Uhr', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Gestern um 02:00 Uhr', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [um] LT [Uhr]'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [um] LT [Uhr]'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [um] LT [Uhr]'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[letzten] dddd [um] LT [Uhr]'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[letzten] dddd [um] LT [Uhr]'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[letzten] dddd [um] LT [Uhr]'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('el'); + + test('parse', function (assert) { + var i, + tests = 'Ιανουάριος Ιαν_Φεβρουάριος Φεβ_Μάρτιος Μαρ_Απρίλιος Απρ_Μάιος Μαϊ_Ιούνιος Ιουν_Ιούλιος Ιουλ_Αύγουστος Αυγ_Σεπτέμβριος Σεπ_Οκτώβριος Οκτ_Νοέμβριος Νοε_Δεκέμβριος Δεκ'.split('_'); + + function equalTest(input, mmm, i) { + assert.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('parse meridiem', function (assert) { + var i, + b = moment(), + meridiemTests = [ + // h a patterns, expected hours, isValid + ['10 πμ', 10, true], + ['10 μμ', 22, true], + ['10 π.μ.', 10, true], + ['10 μ.μ.', 22, true], + ['10 π', 10, true], + ['10 μ', 22, true], + ['10 ΠΜ', 10, true], + ['10 ΜΜ', 22, true], + ['10 Π.Μ.', 10, true], + ['10 Μ.Μ.', 22, true], + ['10 Π', 10, true], + ['10 Μ', 22, true], + ['10 am', 10, false], + ['10 pm', 10, false] + ]; + + // test that a formatted moment including meridiem string can be parsed back to the same moment + assert.ok(b.isSame(moment(b.format('h:mm:ss a'), 'h:mm:ss a', 'el', true), 'seconds'), b.format('h:mm:ss a') + ' should be equal to ' + moment(b.format('h:mm:ss a'), 'h:mm:ss a', 'el', true).format('h:mm:ss a')); + + // test that a formatted moment having a meridiem string can be parsed with strict flag + assert.ok(moment(b.format('h:mm:ss a'), 'h:mm:ss a', 'el', true).isValid(), b.format('h:mm:ss a') + ' should be parsed as valid'); + + for (i = 0; i < meridiemTests.length; i++) { + assert.equal(moment(meridiemTests[i][0], 'h a', 'el', true).hours(), meridiemTests[i][1], moment(meridiemTests[i][0], 'h a', 'el', true).hours() + ' should be ' + meridiemTests[i][1]); + assert.ok(moment(meridiemTests[i][0], 'h a', 'el', true).isValid() === meridiemTests[i][2], meridiemTests[i][0] + ' ----> ' + meridiemTests[i][2]); + } + }); + + test('format', function (assert) { + 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'], + ['LTS', '3:25:50 ΜΜ'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1η', '1η'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2η', '2η'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3η', '3η'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4η', '4η'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5η', '5η'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6η', '6η'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7η', '7η'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8η', '8η'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9η', '9η'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10η', '10η'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11η', '11η'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12η', '12η'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13η', '13η'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14η', '14η'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15η', '15η'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16η', '16η'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17η', '17η'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18η', '18η'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19η', '19η'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20η', '20η'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21η', '21η'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22η', '22η'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23η', '23η'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24η', '24η'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25η', '25η'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26η', '26η'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27η', '27η'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28η', '28η'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29η', '29η'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30η', '30η'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31η', '31η'); + }); + + test('format month', function (assert) { + var i, + expected = 'Ιανουάριος Ιαν_Φεβρουάριος Φεβ_Μάρτιος Μαρ_Απρίλιος Απρ_Μάιος Μαϊ_Ιούνιος Ιουν_Ιούλιος Ιουλ_Αύγουστος Αυγ_Σεπτέμβριος Σεπ_Οκτώβριος Οκτ_Νοέμβριος Νοε_Δεκέμβριος Δεκ'.split('_'); + + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var i, + expected = 'Κυριακή Κυρ Κυ_Δευτέρα Δευ Δε_Τρίτη Τρι Τρ_Τετάρτη Τετ Τε_Πέμπτη Πεμ Πε_Παρασκευή Παρ Πα_Σάββατο Σαβ Σα'.split('_'); + + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'λίγα δευτερόλεπτα', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'ένα λεπτό', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'ένα λεπτό', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 λεπτά', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 λεπτά', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'μία ώρα', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'μία ώρα', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 ώρες', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 ώρες', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 ώρες', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'μία μέρα', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'μία μέρα', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 μέρες', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'μία μέρα', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 μέρες', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 μέρες', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ένας μήνας', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ένας μήνας', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ένας μήνας', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 μήνες', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 μήνες', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 μήνες', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ένας μήνας', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 μήνες', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ένας χρόνος', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 χρόνια', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ένας χρόνος', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 χρόνια', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'σε λίγα δευτερόλεπτα', 'prefix'); + assert.equal(moment(0).from(30000), 'λίγα δευτερόλεπτα πριν', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'λίγα δευτερόλεπτα πριν', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'σε λίγα δευτερόλεπτα', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'σε 5 μέρες', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Σήμερα στις 2:00 ΠΜ', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Σήμερα στις 2:25 ΠΜ', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Σήμερα στις 3:00 ΠΜ', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Αύριο στις 2:00 ΠΜ', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Σήμερα στη 1:00 ΠΜ', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Χθες στις 2:00 ΠΜ', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.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); + assert.equal(m.calendar(), m.format('dddd [στις] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [στις] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m, dayString; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + dayString = m.day() === 6 ? '[το προηγούμενο Σάββατο]' : '[την προηγούμενη] dddd'; + assert.equal(m.calendar(), m.format(dayString + ' [' + (m.hours() % 12 === 1 ? 'στη' : 'στις') + '] LT'), 'Today - ' + i + ' days current time'); + m.hours(1).minutes(30).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(dayString + ' [στη] LT'), 'Today - ' + i + ' days one o clock'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(dayString + ' [στις] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(dayString + ' [στις] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 52, 'Dec 31 2006 should be week 52'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 30]).week(), 52, 'Dec 30 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 52, 'Dec 29 2002 should be week 52'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 52, 'Dec 28 2008 should be week 52'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 52, 'Dec 27 2009 should be week 52'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 2]).week(), 53, 'Jan 2 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 9]).week(), 1, 'Jan 9 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 51, 'Dec 26 2010 should be week 51'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 8]).week(), 1, 'Jan 8 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday format', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52η', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1η', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1η', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2η', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2η', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('en-au'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '3:25:50 PM'], + ['L', '14/02/2010'], + ['LL', '14 February 2010'], + ['LLL', '14 February 2010 3:25 PM'], + ['LLLL', 'Sunday, 14 February 2010 3:25 PM'], + ['l', '14/2/2010'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1st', '1st'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2nd', '2nd'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3rd', '3rd'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4th', '4th'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5th', '5th'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6th', '6th'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7th', '7th'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8th', '8th'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9th', '9th'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10th', '10th'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11th', '11th'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12th', '12th'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13th', '13th'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14th', '14th'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15th', '15th'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16th', '16th'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17th', '17th'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18th', '18th'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19th', '19th'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20th', '20th'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21st', '21st'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22nd', '22nd'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23rd', '23rd'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24th', '24th'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25th', '25th'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26th', '26th'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27th', '27th'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28th', '28th'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29th', '29th'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30th', '30th'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31st', '31st'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Sunday Sun Su_Monday Mon Mo_Tuesday Tue Tu_Wednesday Wed We_Thursday Thu Th_Friday Fri Fr_Saturday Sat Sa'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'a few seconds', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'a minute', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'a minute', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutes', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutes', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'an hour', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'an hour', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 hours', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 hours', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 hours', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'a day', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'a day', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 days', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'a day', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 days', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 days', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'a month', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'a month', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'a month', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 months', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 months', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 months', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'a month', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 months', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'a year', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 years', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'a year', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 years', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'in a few seconds', 'prefix'); + assert.equal(moment(0).from(30000), 'a few seconds ago', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'a few seconds ago', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'in a few seconds', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'in 5 days', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Today at 2:00 AM', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Today at 2:25 AM', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Today at 3:00 AM', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Tomorrow at 2:00 AM', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Today at 1:00 AM', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Yesterday at 2:00 AM', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [at] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [at] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [at] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[Last] dddd [at] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[Last] dddd [at] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[Last] dddd [at] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52nd', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1st', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1st', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2nd', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2nd', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testStr; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testStr = moment(ordinalStr, 'YYYY MM Do').format('YYYY MM D'); + assert.equal(testStr, '2014 01 ' + i, 'lenient ordinal parsing ' + i); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testStr; + for (i = 1; i <= 31; ++i) { + testStr = moment('2014 01 ' + i, 'YYYY MM Do').format('YYYY MM D'); + assert.equal(testStr, '2014 01 ' + i, + 'lenient ordinal parsing of number ' + i); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MMM Do'); + testMoment = moment(ordinalStr, 'YYYY MMM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('en-ca'); + + test('parse', function (assert) { + 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) { + assert.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('format', function (assert) { + 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'], + ['LTS', '3:25:50 PM'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1st', '1st'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2nd', '2nd'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3rd', '3rd'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4th', '4th'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5th', '5th'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6th', '6th'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7th', '7th'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8th', '8th'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9th', '9th'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10th', '10th'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11th', '11th'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12th', '12th'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13th', '13th'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14th', '14th'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15th', '15th'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16th', '16th'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17th', '17th'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18th', '18th'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19th', '19th'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20th', '20th'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21st', '21st'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22nd', '22nd'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23rd', '23rd'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24th', '24th'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25th', '25th'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26th', '26th'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27th', '27th'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28th', '28th'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29th', '29th'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30th', '30th'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31st', '31st'); + }); + + test('format month', function (assert) { + 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++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'a few seconds', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'a minute', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'a minute', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutes', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutes', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'an hour', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'an hour', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 hours', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 hours', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 hours', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'a day', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'a day', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 days', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'a day', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 days', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 days', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'a month', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'a month', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'a month', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 months', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 months', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 months', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'a month', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 months', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'a year', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 years', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'a year', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 years', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'in a few seconds', 'prefix'); + assert.equal(moment(0).from(30000), 'a few seconds ago', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'a few seconds ago', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'in a few seconds', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'in 5 days', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Today at 2:00 AM', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Today at 2:25 AM', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Today at 3:00 AM', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Tomorrow at 2:00 AM', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Today at 1:00 AM', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Yesterday at 2:00 AM', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [at] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [at] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [at] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[Last] dddd [at] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[Last] dddd [at] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[Last] dddd [at] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday format', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1st', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1st', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2nd', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2nd', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3rd', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('en-gb'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1st', '1st'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2nd', '2nd'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3rd', '3rd'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4th', '4th'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5th', '5th'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6th', '6th'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7th', '7th'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8th', '8th'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9th', '9th'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10th', '10th'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11th', '11th'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12th', '12th'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13th', '13th'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14th', '14th'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15th', '15th'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16th', '16th'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17th', '17th'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18th', '18th'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19th', '19th'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20th', '20th'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21st', '21st'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22nd', '22nd'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23rd', '23rd'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24th', '24th'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25th', '25th'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26th', '26th'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27th', '27th'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28th', '28th'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29th', '29th'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30th', '30th'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31st', '31st'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Sunday Sun Su_Monday Mon Mo_Tuesday Tue Tu_Wednesday Wed We_Thursday Thu Th_Friday Fri Fr_Saturday Sat Sa'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'a few seconds', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'a minute', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'a minute', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutes', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutes', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'an hour', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'an hour', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 hours', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 hours', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 hours', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'a day', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'a day', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 days', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'a day', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 days', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 days', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'a month', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'a month', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'a month', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 months', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 months', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 months', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'a month', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 months', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'a year', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 years', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'a year', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 years', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'in a few seconds', 'prefix'); + assert.equal(moment(0).from(30000), 'a few seconds ago', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'a few seconds ago', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'in a few seconds', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'in 5 days', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Today at 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Today at 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Today at 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Tomorrow at 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Today at 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Yesterday at 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [at] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [at] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [at] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[Last] dddd [at] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[Last] dddd [at] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[Last] dddd [at] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52nd', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1st', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1st', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2nd', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2nd', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('en'); + + test('parse', function (assert) { + 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) { + assert.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('format', function (assert) { + 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'], + ['LTS', '3:25:50 PM'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1st', '1st'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2nd', '2nd'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3rd', '3rd'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4th', '4th'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5th', '5th'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6th', '6th'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7th', '7th'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8th', '8th'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9th', '9th'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10th', '10th'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11th', '11th'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12th', '12th'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13th', '13th'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14th', '14th'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15th', '15th'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16th', '16th'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17th', '17th'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18th', '18th'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19th', '19th'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20th', '20th'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21st', '21st'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22nd', '22nd'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23rd', '23rd'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24th', '24th'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25th', '25th'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26th', '26th'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27th', '27th'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28th', '28th'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29th', '29th'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30th', '30th'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31st', '31st'); + }); + + test('format month', function (assert) { + 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++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'a few seconds', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'a minute', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'a minute', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutes', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutes', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'an hour', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'an hour', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 hours', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 hours', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 hours', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'a day', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'a day', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 days', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'a day', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 days', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 days', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'a month', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'a month', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'a month', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 months', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 months', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 months', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'a month', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 months', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'a year', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 years', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'a year', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 years', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'in a few seconds', 'prefix'); + assert.equal(moment(0).from(30000), 'a few seconds ago', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'a few seconds ago', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'in a few seconds', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'in 5 days', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Today at 2:00 AM', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Today at 2:25 AM', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Today at 3:00 AM', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Tomorrow at 2:00 AM', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Today at 1:00 AM', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Yesterday at 2:00 AM', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [at] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [at] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [at] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[Last] dddd [at] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[Last] dddd [at] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[Last] dddd [at] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday format', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1st', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1st', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2nd', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2nd', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3rd', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('eo'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1a', '1a'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2a', '2a'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3a', '3a'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4a', '4a'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5a', '5a'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6a', '6a'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7a', '7a'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8a', '8a'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9a', '9a'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10a', '10a'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11a', '11a'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12a', '12a'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13a', '13a'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14a', '14a'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15a', '15a'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16a', '16a'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17a', '17a'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18a', '18a'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19a', '19a'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20a', '20a'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21a', '21a'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22a', '22a'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23a', '23a'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24a', '24a'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25a', '25a'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26a', '26a'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27a', '27a'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28a', '28a'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29a', '29a'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30a', '30a'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31a', '31a'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'sekundoj', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'minuto', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'minuto', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutoj', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutoj', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'horo', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'horo', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 horoj', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 horoj', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 horoj', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'tago', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'tago', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 tagoj', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'tago', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 tagoj', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 tagoj', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'monato', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'monato', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'monato', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 monatoj', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 monatoj', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 monatoj', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'monato', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 monatoj', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'jaro', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 jaroj', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'jaro', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 jaroj', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'je sekundoj', 'je prefix'); + assert.equal(moment(0).from(30000), 'antaŭ sekundoj', 'antaŭ prefix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'antaŭ sekundoj', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'je sekundoj', 'je sekundoj'); + assert.equal(moment().add({d: 5}).fromNow(), 'je 5 tagoj', 'je 5 tagoj'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Hodiaŭ je 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Hodiaŭ je 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Hodiaŭ je 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Morgaŭ je 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Hodiaŭ je 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Hieraŭ je 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [je] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [je] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [je] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[pasinta] dddd [je] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[pasinta] dddd [je] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[pasinta] dddd [je] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1a', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1a', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2a', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2a', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3a', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('es'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['YYYY-MMM-DD', '2010-Feb-14'], + ['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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'unos segundos', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'un minuto', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'un minuto', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutos', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutos', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'una hora', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'una hora', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 horas', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 horas', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 horas', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'un día', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'un día', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 días', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'un día', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 días', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 días', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'un mes', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'un mes', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'un mes', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 meses', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 meses', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 meses', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'un mes', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 meses', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'un año', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 años', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'un año', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 años', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'en unos segundos', 'prefix'); + assert.equal(moment(0).from(30000), 'hace unos segundos', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'hace unos segundos', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'en unos segundos', 'en unos segundos'); + assert.equal(moment().add({d: 5}).fromNow(), 'en 5 días', 'en 5 días'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'hoy a las 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'hoy a las 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'hoy a las 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'mañana a las 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).add({d: 1, h : -1}).calendar(), 'mañana a la 1:00', 'tomorrow minus 1 hour'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'hoy a la 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'ayer a las 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.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); + assert.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); + assert.equal(m.calendar(), m.format('dddd [a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.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); + assert.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); + assert.equal(m.calendar(), m.format('[el] dddd [pasado a la' + ((m.hours() !== 1) ? 's' : '') + '] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52º', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1º', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1º', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2º', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2º', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('et'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'paar sekundit', '44 seconds = paar sekundit'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'üks minut', '45 seconds = üks minut'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'üks minut', '89 seconds = üks minut'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutit', '90 seconds = 2 minutit'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutit', '44 minutes = 44 minutit'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'üks tund', '45 minutes = tund aega'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'üks tund', '89 minutes = üks tund'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 tundi', '90 minutes = 2 tundi'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 tundi', '5 hours = 5 tundi'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 tundi', '21 hours = 21 tundi'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'üks päev', '22 hours = üks päev'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'üks päev', '35 hours = üks päev'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 päeva', '36 hours = 2 päeva'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'üks päev', '1 day = üks päev'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 päeva', '5 days = 5 päeva'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 päeva', '25 days = 25 päeva'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'üks kuu', '26 days = üks kuu'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'üks kuu', '30 days = üks kuu'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'üks kuu', '43 days = üks kuu'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 kuud', '46 days = 2 kuud'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 kuud', '75 days = 2 kuud'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 kuud', '76 days = 3 kuud'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'üks kuu', '1 month = üks kuu'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 kuud', '5 months = 5 kuud'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'üks aasta', '345 days = üks aasta'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 aastat', '548 days = 2 aastat'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'üks aasta', '1 year = üks aasta'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 aastat', '5 years = 5 aastat'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'mõne sekundi pärast', 'prefix'); + assert.equal(moment(0).from(30000), 'mõni sekund tagasi', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'mõni sekund tagasi', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'mõne sekundi pärast', 'in a few seconds'); + assert.equal(moment().subtract({s: 30}).fromNow(), 'mõni sekund tagasi', 'a few seconds ago'); + + assert.equal(moment().add({m: 1}).fromNow(), 'ühe minuti pärast', 'in a minute'); + assert.equal(moment().subtract({m: 1}).fromNow(), 'üks minut tagasi', 'a minute ago'); + + assert.equal(moment().add({m: 5}).fromNow(), '5 minuti pärast', 'in 5 minutes'); + assert.equal(moment().subtract({m: 5}).fromNow(), '5 minutit tagasi', '5 minutes ago'); + + assert.equal(moment().add({d: 1}).fromNow(), 'ühe päeva pärast', 'in one day'); + assert.equal(moment().subtract({d: 1}).fromNow(), 'üks päev tagasi', 'one day ago'); + + assert.equal(moment().add({d: 5}).fromNow(), '5 päeva pärast', 'in 5 days'); + assert.equal(moment().subtract({d: 5}).fromNow(), '5 päeva tagasi', '5 days ago'); + + assert.equal(moment().add({M: 1}).fromNow(), 'kuu aja pärast', 'in a month'); + assert.equal(moment().subtract({M: 1}).fromNow(), 'kuu aega tagasi', 'a month ago'); + + assert.equal(moment().add({M: 5}).fromNow(), '5 kuu pärast', 'in 5 months'); + assert.equal(moment().subtract({M: 5}).fromNow(), '5 kuud tagasi', '5 months ago'); + + assert.equal(moment().add({y: 1}).fromNow(), 'ühe aasta pärast', 'in a year'); + assert.equal(moment().subtract({y: 1}).fromNow(), 'aasta tagasi', 'a year ago'); + + assert.equal(moment().add({y: 5}).fromNow(), '5 aasta pärast', 'in 5 years'); + assert.equal(moment().subtract({y: 5}).fromNow(), '5 aastat tagasi', '5 years ago'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Täna, 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Täna, 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Täna, 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Homme, 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Täna, 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Eile, 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('[Järgmine] dddd LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[Järgmine] dddd LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[Järgmine] dddd LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[Eelmine] dddd LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[Eelmine] dddd LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[Eelmine] dddd LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 nädal tagasi'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), '1 nädala pärast'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 nädalat tagasi'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), '2 nädala pärast'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('eu'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'igandea ig. ig_astelehena al. al_asteartea ar. ar_asteazkena az. az_osteguna og. og_ostirala ol. ol_larunbata lr. lr'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'segundo batzuk', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'minutu bat', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'minutu bat', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutu', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutu', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ordu bat', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ordu bat', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 ordu', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 ordu', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 ordu', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'egun bat', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'egun bat', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 egun', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'egun bat', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 egun', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 egun', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'hilabete bat', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'hilabete bat', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'hilabete bat', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 hilabete', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 hilabete', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 hilabete', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'hilabete bat', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 hilabete', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'urte bat', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 urte', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'urte bat', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 urte', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'segundo batzuk barru', 'prefix'); + assert.equal(moment(0).from(30000), 'duela segundo batzuk', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'duela segundo batzuk', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'segundo batzuk barru', 'in seconds'); + assert.equal(moment().add({d: 5}).fromNow(), '5 egun barru', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'gaur 02:00etan', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'gaur 02:25etan', 'now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'gaur 03:00etan', 'now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'bihar 02:00etan', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'gaur 01:00etan', 'now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'atzo 02:00etan', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd LT[etan]'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd LT[etan]'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd LT[etan]'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[aurreko] dddd LT[etan]'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[aurreko] dddd LT[etan]'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[aurreko] dddd LT[etan]'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1.', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1.', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2.', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2.', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3.', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('fa'); + + test('parse', function (assert) { + var tests = 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'یک\u200cشنبه، فوریه ۱۴م ۲۰۱۰، ۳:۲۵:۵۰ بعد از ظهر'], + ['ddd, hA', 'یک\u200cشنبه، ۳بعد از ظهر'], + ['M Mo MM MMMM MMM', '۲ ۲م ۰۲ فوریه فوریه'], + ['YYYY YY', '۲۰۱۰ ۱۰'], + ['D Do DD', '۱۴ ۱۴م ۱۴'], + ['d do dddd ddd dd', '۰ ۰م یک\u200cشنبه یک\u200cشنبه ی'], + ['DDD DDDo DDDD', '۴۵ ۴۵م ۰۴۵'], + ['w wo ww', '۸ ۸م ۰۸'], + ['h hh', '۳ ۰۳'], + ['H HH', '۱۵ ۱۵'], + ['m mm', '۲۵ ۲۵'], + ['s ss', '۵۰ ۵۰'], + ['a A', 'بعد از ظهر بعد از ظهر'], + ['DDDo [روز سال]', '۴۵م روز سال'], + ['LTS', '۱۵:۲۵:۵۰'], + ['L', '۱۴/۰۲/۲۰۱۰'], + ['LL', '۱۴ فوریه ۲۰۱۰'], + ['LLL', '۱۴ فوریه ۲۰۱۰ ۱۵:۲۵'], + ['LLLL', 'یک\u200cشنبه، ۱۴ فوریه ۲۰۱۰ ۱۵:۲۵'], + ['l', '۱۴/۲/۲۰۱۰'], + ['ll', '۱۴ فوریه ۲۰۱۰'], + ['lll', '۱۴ فوریه ۲۰۱۰ ۱۵:۲۵'], + ['llll', 'یک\u200cشنبه، ۱۴ فوریه ۲۰۱۰ ۱۵:۲۵'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '۱م', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '۲م', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '۳م', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '۴م', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '۵م', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '۶م', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '۷م', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '۸م', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '۹م', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '۱۰م', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '۱۱م', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '۱۲م', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '۱۳م', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '۱۴م', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '۱۵م', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '۱۶م', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '۱۷م', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '۱۸م', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '۱۹م', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '۲۰م', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '۲۱م', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '۲۲م', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '۲۳م', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '۲۴م', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '۲۵م', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '۲۶م', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '۲۷م', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '۲۸م', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '۲۹م', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '۳۰م', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '۳۱م', '31'); + }); + + test('format month', function (assert) { + var expected = 'ژانویه ژانویه_فوریه فوریه_مارس مارس_آوریل آوریل_مه مه_ژوئن ژوئن_ژوئیه ژوئیه_اوت اوت_سپتامبر سپتامبر_اکتبر اکتبر_نوامبر نوامبر_دسامبر دسامبر'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'یک\u200cشنبه یک\u200cشنبه ی_دوشنبه دوشنبه د_سه\u200cشنبه سه\u200cشنبه س_چهارشنبه چهارشنبه چ_پنج\u200cشنبه پنج\u200cشنبه پ_جمعه جمعه ج_شنبه شنبه ش'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'چندین ثانیه', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'یک دقیقه', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'یک دقیقه', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '۲ دقیقه', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '۴۴ دقیقه', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'یک ساعت', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'یک ساعت', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '۲ ساعت', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '۵ ساعت', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '۲۱ ساعت', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'یک روز', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'یک روز', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '۲ روز', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'یک روز', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '۵ روز', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '۲۵ روز', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'یک ماه', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'یک ماه', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'یک ماه', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '۲ ماه', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '۲ ماه', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '۳ ماه', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'یک ماه', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '۵ ماه', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'یک سال', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '۲ سال', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'یک سال', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '۵ سال', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'در چندین ثانیه', 'prefix'); + assert.equal(moment(0).from(30000), 'چندین ثانیه پیش', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'چندین ثانیه پیش', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'در چندین ثانیه', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'در ۵ روز', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'امروز ساعت ۰۲:۰۰', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'امروز ساعت ۰۲:۲۵', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'امروز ساعت ۰۳:۰۰', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'فردا ساعت ۰۲:۰۰', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'امروز ساعت ۰۱:۰۰', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'دیروز ساعت ۰۲:۰۰', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [ساعت] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [ساعت] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [ساعت] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [پیش ساعت] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [پیش ساعت] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [پیش ساعت] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 31]).week(), 1, 'Dec 31 2011 should be week 1'); + assert.equal(moment([2012, 0, 6]).week(), 1, 'Jan 6 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 2, 'Jan 7 2012 should be week 2'); + assert.equal(moment([2012, 0, 13]).week(), 2, 'Jan 13 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 3, 'Jan 14 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 30]).week(), 1, 'Dec 30 2006 should be week 1'); + assert.equal(moment([2007, 0, 5]).week(), 1, 'Jan 5 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 2, 'Jan 6 2007 should be week 2'); + assert.equal(moment([2007, 0, 12]).week(), 2, 'Jan 12 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 3, 'Jan 13 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 1, 'Dec 29 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 4]).week(), 1, 'Jan 4 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 2, 'Jan 5 2008 should be week 2'); + assert.equal(moment([2008, 0, 11]).week(), 2, 'Jan 11 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 3, 'Jan 12 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 28]).week(), 1, 'Dec 28 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 3]).week(), 1, 'Jan 3 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 2, 'Jan 4 2003 should be week 2'); + assert.equal(moment([2003, 0, 10]).week(), 2, 'Jan 10 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 3, 'Jan 11 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 27]).week(), 1, 'Dec 27 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 2]).week(), 1, 'Jan 2 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 2, 'Jan 3 2009 should be week 2'); + assert.equal(moment([2009, 0, 9]).week(), 2, 'Jan 9 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 3, 'Jan 10 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 26]).week(), 1, 'Dec 26 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 2, 'Jan 2 2010 should be week 2'); + assert.equal(moment([2010, 0, 8]).week(), 2, 'Jan 8 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 3, 'Jan 9 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 7]).week(), 1, 'Jan 7 2011 should be week 1'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 14]).week(), 2, 'Jan 14 2011 should be week 2'); + assert.equal(moment([2011, 0, 15]).week(), 3, 'Jan 15 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 31]).format('w ww wo'), '۱ ۰۱ ۱م', 'Dec 31 2011 should be week 1'); + assert.equal(moment([2012, 0, 6]).format('w ww wo'), '۱ ۰۱ ۱م', 'Jan 6 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '۲ ۰۲ ۲م', 'Jan 7 2012 should be week 2'); + assert.equal(moment([2012, 0, 13]).format('w ww wo'), '۲ ۰۲ ۲م', 'Jan 13 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '۳ ۰۳ ۳م', 'Jan 14 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('fi'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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ä'], + ['LTS', '15.25.50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1st'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2nd'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3rd'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4th'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5th'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6th'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7th'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8th'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9th'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10th'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11th'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12th'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13th'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14th'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15th'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16th'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17th'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18th'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19th'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20th'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21st'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22nd'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23rd'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24th'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25th'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26th'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27th'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28th'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29th'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30th'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31st'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'sunnuntai su su_maanantai ma ma_tiistai ti ti_keskiviikko ke ke_torstai to to_perjantai pe pe_lauantai la la'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'muutama sekunti', '44 seconds = few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'minuutti', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'minuutti', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), 'kaksi minuuttia', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuuttia', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'tunti', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'tunti', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), 'kaksi tuntia', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), 'viisi tuntia', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 tuntia', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'päivä', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'päivä', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), 'kaksi päivää', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'päivä', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), 'viisi päivää', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 päivää', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'kuukausi', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'kuukausi', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'kuukausi', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), 'kaksi kuukautta', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), 'kaksi kuukautta', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), 'kolme kuukautta', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'kuukausi', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), 'viisi kuukautta', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'vuosi', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), 'kaksi vuotta', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'vuosi', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), 'viisi vuotta', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'muutaman sekunnin päästä', 'prefix'); + assert.equal(moment(0).from(30000), 'muutama sekunti sitten', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'muutama sekunti sitten', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'muutaman sekunnin päästä', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'viiden päivän päästä', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'tänään klo 02.00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'tänään klo 02.25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'tänään klo 03.00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'huomenna klo 02.00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'tänään klo 01.00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'eilen klo 02.00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [klo] LT'), 'today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [klo] LT'), 'today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [klo] LT'), 'today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[viime] dddd[na] [klo] LT'), 'today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.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); + assert.equal(m.calendar(), m.format('[viime] dddd[na] [klo] LT'), 'today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), 'yksi viikko sitten'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'yhden viikon päästä'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), 'kaksi viikkoa sitten'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'kaden viikon päästä'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('fo'); + + test('parse', function (assert) { + var tests = 'januar jan_februar feb_mars mar_apríl apr_mai mai_juni jun_juli jul_august aug_september sep_oktober okt_november nov_desember des'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd [tann] Do MMMM YYYY, h:mm:ss a', 'sunnudagur tann 14. februar 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. 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'], + ['[tann] DDDo [dagin á árinum]', 'tann 45. dagin á árinum'], + ['LTS', '15:25:50'], + ['L', '14/02/2010'], + ['LL', '14 februar 2010'], + ['LLL', '14 februar 2010 15:25'], + ['LLLL', 'sunnudagur 14. februar, 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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + var expected = 'januar jan_februar feb_mars mar_apríl apr_mai mai_juni jun_juli jul_august aug_september sep_oktober okt_november nov_desember des'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'sunnudagur sun su_mánadagur mán má_týsdagur týs tý_mikudagur mik mi_hósdagur hós hó_fríggjadagur frí fr_leygardagur ley le'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'fá sekund', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'ein minutt', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'ein minutt', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuttir', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuttir', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ein tími', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ein tími', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 tímar', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 tímar', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 tímar', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'ein dagur', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'ein dagur', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dagar', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'ein dagur', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dagar', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dagar', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ein mánaði', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ein mánaði', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ein mánaði', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mánaðir', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mánaðir', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mánaðir', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ein mánaði', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mánaðir', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'eitt ár', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 ár', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'eitt ár', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 ár', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'um fá sekund', 'prefix'); + assert.equal(moment(0).from(30000), 'fá sekund síðani', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'fá sekund síðani', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'um fá sekund', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'um 5 dagar', 'in 5 days'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('fr-ca'); + + test('parse', function (assert) { + 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) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1er', '1er'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + }); + + test('format month', function (assert) { + 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++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'quelques secondes', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'une minute', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'une minute', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutes', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutes', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'une heure', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'une heure', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 heures', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 heures', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 heures', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'un jour', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'un jour', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 jours', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'un jour', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 jours', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 jours', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'un mois', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'un mois', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'un mois', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mois', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mois', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mois', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'un mois', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mois', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'un an', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 ans', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'un an', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 ans', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'dans quelques secondes', 'prefix'); + assert.equal(moment(0).from(30000), 'il y a quelques secondes', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'dans quelques secondes', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'dans 5 jours', 'in 5 days'); + }); + + test('same day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Aujourd\'hui à 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Aujourd\'hui à 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Aujourd\'hui à 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Demain à 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Aujourd\'hui à 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Hier à 02:00', 'yesterday at the same time'); + }); + + test('same next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [à] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [à] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [à] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('same last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [dernier à] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [dernier à] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [dernier à] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('same all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday format', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1er', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1er', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('fr'); + + test('parse', function (assert) { + 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('_'), + i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1er', '1er'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'dimanche dim. Di_lundi lun. Lu_mardi mar. Ma_mercredi mer. Me_jeudi jeu. Je_vendredi ven. Ve_samedi sam. Sa'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'quelques secondes', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'une minute', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'une minute', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutes', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutes', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'une heure', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'une heure', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 heures', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 heures', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 heures', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'un jour', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'un jour', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 jours', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'un jour', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 jours', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 jours', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'un mois', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'un mois', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'un mois', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mois', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mois', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mois', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'un mois', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mois', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'un an', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 ans', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'un an', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 ans', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'dans quelques secondes', 'prefix'); + assert.equal(moment(0).from(30000), 'il y a quelques secondes', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'dans quelques secondes', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'dans 5 jours', 'in 5 days'); + }); + + test('same day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Aujourd\'hui à 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Aujourd\'hui à 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Aujourd\'hui à 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Demain à 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Aujourd\'hui à 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Hier à 02:00', 'yesterday at the same time'); + }); + + test('same next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [à] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [à] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [à] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('same last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [dernier à] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [dernier à] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [dernier à] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('same all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1er', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1er', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('fy'); + + test('parse', function (assert) { + var tests = 'jannewaris jan._febrewaris feb._maart mrt._april apr._maaie mai._juny jun._july jul._augustus aug._septimber sep._oktober okt._novimber nov._desimber des.'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, HH:mm:ss', 'snein, febrewaris 14de 2010, 15:25:50'], + ['ddd, HH', 'si., 15'], + ['M Mo MM MMMM MMM', '2 2de 02 febrewaris feb.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14de 14'], + ['d do dddd ddd dd', '0 0de snein si. Si'], + ['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'], + ['LTS', '15:25:50'], + ['L', '14-02-2010'], + ['LL', '14 febrewaris 2010'], + ['LLL', '14 febrewaris 2010 15:25'], + ['LLLL', 'snein 14 febrewaris 2010 15:25'], + ['l', '14-2-2010'], + ['ll', '14 feb. 2010'], + ['lll', '14 feb. 2010 15:25'], + ['llll', 'si. 14 feb. 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1ste', '1ste'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2de', '2de'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3de', '3de'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4de', '4de'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5de', '5de'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6de', '6de'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7de', '7de'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8ste', '8ste'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9de', '9de'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10de', '10de'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11de', '11de'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12de', '12de'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13de', '13de'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14de', '14de'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15de', '15de'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16de', '16de'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17de', '17de'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18de', '18de'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19de', '19de'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20ste', '20ste'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21ste', '21ste'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22ste', '22ste'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23ste', '23ste'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24ste', '24ste'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25ste', '25ste'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26ste', '26ste'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27ste', '27ste'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28ste', '28ste'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29ste', '29ste'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30ste', '30ste'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31ste', '31ste'); + }); + + test('format month', function (assert) { + var expected = 'jannewaris jan._febrewaris feb._maart mrt._april apr._maaie mai_juny jun._july jul._augustus aug._septimber sep._oktober okt._novimber nov._desimber des.'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'snein si. Si_moandei mo. Mo_tiisdei ti. Ti_woansdei wo. Wo_tongersdei to. To_freed fr. Fr_sneon so. So'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'in pear sekonden', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'ien minút', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'ien minút', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuten', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuten', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ien oere', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ien oere', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 oeren', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 oeren', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 oeren', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'ien dei', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'ien dei', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dagen', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'ien dei', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dagen', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dagen', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ien moanne', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ien moanne', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ien moanne', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 moannen', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 moannen', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 moannen', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ien moanne', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 moannen', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ien jier', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 jierren', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ien jier', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 jierren', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'oer in pear sekonden', 'prefix'); + assert.equal(moment(0).from(30000), 'in pear sekonden lyn', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'in pear sekonden lyn', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'oer in pear sekonden', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'oer 5 dagen', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'hjoed om 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'hjoed om 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'hjoed om 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'moarn om 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'hjoed om 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'juster om 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [om] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [om] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [om] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[ôfrûne] dddd [om] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[ôfrûne] dddd [om] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[ôfrûne] dddd [om] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('month abbreviation', function (assert) { + assert.equal(moment([2012, 5, 23]).format('D-MMM-YYYY'), '23-jun-2012', 'format month abbreviation surrounded by dashes should not include a dot'); + assert.equal(moment([2012, 5, 23]).format('D MMM YYYY'), '23 jun. 2012', 'format month abbreviation not surrounded by dashes should include a dot'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52ste', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1ste', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1ste', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2de', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2de', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('gl'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Domingo, Febreiro 14º 2010, 3:25:50 pm'], + ['ddd, hA', 'Dom., 3PM'], + ['M Mo MM MMMM MMM', '2 2º 02 Febreiro 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', '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'], + ['LTS', '15:25:50'], + ['L', '14/02/2010'], + ['LL', '14 Febreiro 2010'], + ['LLL', '14 Febreiro 2010 15:25'], + ['LLLL', 'Domingo 14 Febreiro 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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'uns segundos', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'un minuto', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'un minuto', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutos', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutos', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'unha hora', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'unha hora', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 horas', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 horas', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 horas', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'un día', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'un día', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 días', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'un día', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 días', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 días', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'un mes', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'un mes', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'un mes', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 meses', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 meses', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 meses', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'un mes', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 meses', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'un ano', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 anos', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'un ano', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 anos', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'nuns segundos', 'prefix'); + assert.equal(moment(0).from(30000), 'hai uns segundos', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'hai uns segundos', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'nuns segundos', 'en unos segundos'); + assert.equal(moment().add({d: 5}).fromNow(), 'en 5 días', 'en 5 días'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'hoxe ás 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'hoxe ás 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'hoxe ás 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'mañá ás 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).add({d: 1, h : -1}).calendar(), 'mañá á 1:00', 'tomorrow minus 1 hour'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'hoxe á 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'onte á 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.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); + assert.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); + assert.equal(m.calendar(), m.format('dddd [' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.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); + assert.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); + assert.equal(m.calendar(), m.format('[o] dddd [pasado ' + ((m.hours() !== 1) ? 'ás' : 'a') + '] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('regression tests', function (assert) { + var lastWeek = moment().subtract({d: 4}).hours(1); + assert.equal(lastWeek.calendar(), lastWeek.format('[o] dddd [pasado a] LT'), '1 o\'clock bug'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1º', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1º', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2º', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2º', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3º', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('he'); + + test('parse', function (assert) { + var tests = 'ינואר ינו׳_פברואר פבר׳_מרץ מרץ_אפריל אפר׳_מאי מאי_יוני יוני_יולי יולי_אוגוסט אוג׳_ספטמבר ספט׳_אוקטובר אוק׳_נובמבר נוב׳_דצמבר דצמ׳'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format month', function (assert) { + var expected = 'ינואר ינו׳_פברואר פבר׳_מרץ מרץ_אפריל אפר׳_מאי מאי_יוני יוני_יולי יולי_אוגוסט אוג׳_ספטמבר ספט׳_אוקטובר אוק׳_נובמבר נוב׳_דצמבר דצמ׳'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'ראשון א׳ א|שני ב׳ ב|שלישי ג׳ ג|רביעי ד׳ ד|חמישי ה׳ ה|שישי ו׳ ו|שבת ש׳ ש'.split('|'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'מספר שניות', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'דקה', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'דקה', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 דקות', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 דקות', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'שעה', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'שעה', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), 'שעתיים', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 שעות', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 שעות', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'יום', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'יום', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), 'יומיים', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'יום', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 ימים', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 ימים', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'חודש', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'חודש', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'חודש', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), 'חודשיים', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), 'חודשיים', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 חודשים', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'חודש', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 חודשים', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'שנה', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), 'שנתיים', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 3699}), true), '10 שנים', '345 days = 10 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 7340}), true), '20 שנה', '548 days = 20 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'שנה', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 שנים', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'בעוד מספר שניות', 'prefix'); + assert.equal(moment(0).from(30000), 'לפני מספר שניות', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'לפני מספר שניות', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'בעוד מספר שניות', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'בעוד 5 ימים', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'היום ב־02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'היום ב־02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'היום ב־03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'מחר ב־02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'היום ב־01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'אתמול ב־02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [בשעה] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [בשעה] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [בשעה] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[ביום] dddd [האחרון בשעה] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[ביום] dddd [האחרון בשעה] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[ביום] dddd [האחרון בשעה] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday format', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('hi'); + + test('parse', function (assert) { + var tests = 'जनवरी जन._फ़रवरी फ़र._मार्च मार्च_अप्रैल अप्रै._मई मई_जून जून_जुलाई जुल._अगस्त अग._सितम्बर सित._अक्टूबर अक्टू._नवम्बर नव._दिसम्बर दिस.'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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', 'दोपहर दोपहर'], + ['LTS', 'दोपहर ३:२५:५० बजे'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '१', '१'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '२', '२'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '३', '३'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '४', '४'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '५', '५'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '६', '६'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '७', '७'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '८', '८'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '९', '९'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '१०', '१०'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '११', '११'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '१२', '१२'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '१३', '१३'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '१४', '१४'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '१५', '१५'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '१६', '१६'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '१७', '१७'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '१८', '१८'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '१९', '१९'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '२०', '२०'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '२१', '२१'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '२२', '२२'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '२३', '२३'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '२४', '२४'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '२५', '२५'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '२६', '२६'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '२७', '२७'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '२८', '२८'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '२९', '२९'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '३०', '३०'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '३१', '३१'); + }); + + test('format month', function (assert) { + var expected = 'जनवरी जन._फ़रवरी फ़र._मार्च मार्च_अप्रैल अप्रै._मई मई_जून जून_जुलाई जुल._अगस्त अग._सितम्बर सित._अक्टूबर अक्टू._नवम्बर नव._दिसम्बर दिस.'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'रविवार रवि र_सोमवार सोम सो_मंगलवार मंगल मं_बुधवार बुध बु_गुरूवार गुरू गु_शुक्रवार शुक्र शु_शनिवार शनि श'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'कुछ ही क्षण', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'एक मिनट', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'एक मिनट', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '२ मिनट', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '४४ मिनट', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'एक घंटा', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'एक घंटा', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '२ घंटे', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '५ घंटे', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '२१ घंटे', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'एक दिन', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'एक दिन', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '२ दिन', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'एक दिन', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '५ दिन', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '२५ दिन', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'एक महीने', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'एक महीने', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'एक महीने', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '२ महीने', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '२ महीने', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '३ महीने', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'एक महीने', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '५ महीने', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'एक वर्ष', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '२ वर्ष', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'एक वर्ष', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '५ वर्ष', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'कुछ ही क्षण में', 'prefix'); + assert.equal(moment(0).from(30000), 'कुछ ही क्षण पहले', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'कुछ ही क्षण पहले', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'कुछ ही क्षण में', 'कुछ ही क्षण में'); + assert.equal(moment().add({d: 5}).fromNow(), '५ दिन में', '५ दिन में'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'आज रात २:०० बजे', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'आज रात २:२५ बजे', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 3}).calendar(), 'आज सुबह ५:०० बजे', 'Now plus 3 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'कल रात २:०० बजे', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'आज रात १:०० बजे', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'कल रात २:०० बजे', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd[,] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd[,] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd[,] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[पिछले] dddd[,] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[पिछले] dddd[,] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[पिछले] dddd[,] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('meridiem invariant', function (assert) { + assert.equal(moment([2011, 2, 23, 2, 30]).format('a'), 'रात', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('a'), 'सुबह', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('a'), 'दोपहर', 'during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('a'), 'शाम', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('a'), 'शाम', 'late evening'); + assert.equal(moment([2011, 2, 23, 21, 20]).format('a'), 'रात', 'night'); + + assert.equal(moment([2011, 2, 23, 2, 30]).format('A'), 'रात', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('A'), 'सुबह', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('A'), 'दोपहर', ' during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('A'), 'शाम', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('A'), 'शाम', 'late evening'); + assert.equal(moment([2011, 2, 23, 21, 20]).format('A'), 'रात', 'night'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '१ ०१ १', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '१ ०१ १', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '२ ०२ २', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '२ ०२ २', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '३ ०३ ३', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('meridiem', function (assert) { + var h, m, t1, t2; + for (h = 0; h < 24; ++h) { + for (m = 0; m < 60; m += 15) { + t1 = moment.utc([2000, 0, 1, h, m]); + t2 = moment(t1.format('A h:mm'), 'A h:mm'); + assert.equal(t2.format('HH:mm'), t1.format('HH:mm'), + 'meridiem at ' + t1.format('HH:mm')); + } + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('hr'); + + test('parse', function (assert) { + var tests = 'siječanj sij._veljača velj._ožujak ožu._travanj tra._svibanj svi._lipanj lip._srpanj srp._kolovoz kol._rujan ruj._listopad lis._studeni stu._prosinac pro.'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, Do MMMM YYYY, h:mm:ss a', 'nedjelja, 14. veljača 2010, 3:25:50 pm'], + ['ddd, hA', 'ned., 3PM'], + ['M Mo MM MMMM MMM', '2 2. 02 veljača velj.'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14. 14'], + ['d do dddd ddd dd', '0 0. nedjelja 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'], + ['LTS', '15:25:50'], + ['L', '14. 02. 2010'], + ['LL', '14. veljača 2010'], + ['LLL', '14. veljača 2010 15:25'], + ['LLLL', 'nedjelja, 14. veljača 2010 15:25'], + ['l', '14. 2. 2010'], + ['ll', '14. velj. 2010'], + ['lll', '14. velj. 2010 15:25'], + ['llll', 'ned., 14. velj. 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + var expected = 'siječanj sij._veljača velj._ožujak ožu._travanj tra._svibanj svi._lipanj lip._srpanj srp._kolovoz kol._rujan ruj._listopad lis._studeni stu._prosinac pro.'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'nedjelja ned. ne_ponedjeljak pon. po_utorak uto. ut_srijeda sri. sr_četvrtak čet. če_petak pet. pe_subota sub. su'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'par sekundi', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'jedna minuta', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'jedna minuta', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minute', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuta', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'jedan sat', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'jedan sat', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 sata', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 sati', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 sati', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'dan', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'dan', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dana', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'dan', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dana', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dana', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'mjesec', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'mjesec', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'mjesec', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mjeseca', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mjeseca', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mjeseca', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'mjesec', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mjeseci', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'godinu', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 godine', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'godinu', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 godina', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'za par sekundi', 'prefix'); + assert.equal(moment(0).from(30000), 'prije par sekundi', 'prefix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'prije par sekundi', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'za par sekundi', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'za 5 dana', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'danas u 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'danas u 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'danas u 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'sutra u 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'danas u 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'jučer u 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1.', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1.', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2.', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2.', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3.', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('hu'); + + test('parse', function (assert) { + 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('_'), + i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, HH:mm:ss', 'vasárnap, február 14. 2010, 15:25:50'], + ['ddd, HH', 'vas, 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 dd', '0 0. vasárnap vas 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'], + ['LTS', '15:25:50'], + ['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., vas 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('meridiem', function (assert) { + assert.equal(moment([2011, 2, 23, 0, 0]).format('a'), 'de', 'am'); + assert.equal(moment([2011, 2, 23, 11, 59]).format('a'), 'de', 'am'); + assert.equal(moment([2011, 2, 23, 12, 0]).format('a'), 'du', 'pm'); + assert.equal(moment([2011, 2, 23, 23, 59]).format('a'), 'du', 'pm'); + + assert.equal(moment([2011, 2, 23, 0, 0]).format('A'), 'DE', 'AM'); + assert.equal(moment([2011, 2, 23, 11, 59]).format('A'), 'DE', 'AM'); + assert.equal(moment([2011, 2, 23, 12, 0]).format('A'), 'DU', 'PM'); + assert.equal(moment([2011, 2, 23, 23, 59]).format('A'), 'DU', 'PM'); + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'vasárnap vas_hétfő hét_kedd kedd_szerda sze_csütörtök csüt_péntek pén_szombat szo'.split('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'néhány másodperc', '44 másodperc = néhány másodperc'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'egy perc', '45 másodperc = egy perc'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'egy perc', '89 másodperc = egy perc'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 perc', '90 másodperc = 2 perc'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 perc', '44 perc = 44 perc'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'egy óra', '45 perc = egy óra'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'egy óra', '89 perc = egy óra'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 óra', '90 perc = 2 óra'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 óra', '5 óra = 5 óra'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 óra', '21 óra = 21 óra'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'egy nap', '22 óra = egy nap'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'egy nap', '35 óra = egy nap'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 nap', '36 óra = 2 nap'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'egy nap', '1 nap = egy nap'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 nap', '5 nap = 5 nap'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 nap', '25 nap = 25 nap'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'egy hónap', '26 nap = egy hónap'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'egy hónap', '30 nap = egy hónap'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'egy hónap', '45 nap = egy hónap'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 hónap', '46 nap = 2 hónap'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 hónap', '75 nap = 2 hónap'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 hónap', '76 nap = 3 hónap'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'egy hónap', '1 hónap = egy hónap'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 hónap', '5 hónap = 5 hónap'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'egy év', '345 nap = egy év'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 év', '548 nap = 2 év'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'egy év', '1 év = egy év'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 év', '5 év = 5 év'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'néhány másodperc múlva', 'prefix'); + assert.equal(moment(0).from(30000), 'néhány másodperce', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'néhány másodperce', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'néhány másodperc múlva', 'néhány másodperc múlva'); + assert.equal(moment().add({d: 5}).fromNow(), '5 nap múlva', '5 nap múlva'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'ma 2:00-kor', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'ma 2:25-kor', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'ma 3:00-kor', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'holnap 2:00-kor', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'ma 1:00-kor', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'tegnap 2:00-kor', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m, 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}); + assert.equal(m.calendar(), m.format('[' + days[m.day()] + '] LT[-kor]'), 'today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.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); + assert.equal(m.calendar(), m.format('[' + days[m.day()] + '] LT[-kor]'), 'today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m, 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().subtract({d: i}); + assert.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); + assert.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); + assert.equal(m.calendar(), m.format('[múlt ' + days[m.day()] + '] LT[-kor]'), 'today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), 'egy héte'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'egy hét múlva'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 hete'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), '2 hét múlva'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1.', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1.', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2.', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2.', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3.', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('hy-am'); + + test('parse', function (assert) { + var tests = 'հունվար հնվ_փետրվար փտր_մարտ մրտ_ապրիլ ապր_մայիս մյս_հունիս հնս_հուլիս հլս_օգոստոս օգս_սեպտեմբեր սպտ_հոկտեմբեր հկտ_նոյեմբեր նմբ_դեկտեմբեր դկտ'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('parse exceptional case', function (assert) { + assert.equal(moment('11 մայիսի 1989', ['DD MMMM YYYY']).format('DD-MM-YYYY'), '11-05-1989'); + }); + + test('format', function (assert) { + var a = [ + ['dddd, Do MMMM YYYY, HH:mm:ss', 'կիրակի, 14 փետրվարի 2010, 15: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', '7 7-րդ 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'ցերեկվա ցերեկվա'], + ['[տարվա] DDDo [օրը]', 'տարվա 45-րդ օրը'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format meridiem', function (assert) { + assert.equal(moment([2012, 11, 28, 0, 0]).format('A'), 'գիշերվա', 'night'); + assert.equal(moment([2012, 11, 28, 3, 59]).format('A'), 'գիշերվա', 'night'); + assert.equal(moment([2012, 11, 28, 4, 0]).format('A'), 'առավոտվա', 'morning'); + assert.equal(moment([2012, 11, 28, 11, 59]).format('A'), 'առավոտվա', 'morning'); + assert.equal(moment([2012, 11, 28, 12, 0]).format('A'), 'ցերեկվա', 'afternoon'); + assert.equal(moment([2012, 11, 28, 16, 59]).format('A'), 'ցերեկվա', 'afternoon'); + assert.equal(moment([2012, 11, 28, 17, 0]).format('A'), 'երեկոյան', 'evening'); + assert.equal(moment([2012, 11, 28, 23, 59]).format('A'), 'երեկոյան', 'evening'); + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1-ին', '1-ին'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2-րդ', '2-րդ'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3-րդ', '3-րդ'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4-րդ', '4-րդ'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5-րդ', '5-րդ'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6-րդ', '6-րդ'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7-րդ', '7-րդ'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8-րդ', '8-րդ'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9-րդ', '9-րդ'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10-րդ', '10-րդ'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11-րդ', '11-րդ'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12-րդ', '12-րդ'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13-րդ', '13-րդ'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14-րդ', '14-րդ'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15-րդ', '15-րդ'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16-րդ', '16-րդ'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17-րդ', '17-րդ'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18-րդ', '18-րդ'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19-րդ', '19-րդ'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20-րդ', '20-րդ'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21-րդ', '21-րդ'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22-րդ', '22-րդ'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23-րդ', '23-րդ'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24-րդ', '24-րդ'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25-րդ', '25-րդ'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26-րդ', '26-րդ'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27-րդ', '27-րդ'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28-րդ', '28-րդ'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29-րդ', '29-րդ'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30-րդ', '30-րդ'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31-րդ', '31-րդ'); + }); + + test('format month', function (assert) { + var expected = 'հունվար հնվ_փետրվար փտր_մարտ մրտ_ապրիլ ապր_մայիս մյս_հունիս հնս_հուլիս հլս_օգոստոս օգս_սեպտեմբեր սպտ_հոկտեմբեր հկտ_նոյեմբեր նմբ_դեկտեմբեր դկտ'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format month case', function (assert) { + var months = { + 'nominative': 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_'), + 'accusative': 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_') + }, i; + for (i = 0; i < 12; i++) { + assert.equal(moment([2011, i, 1]).format('D MMMM'), '1 ' + months.accusative[i], '1 ' + months.accusative[i]); + assert.equal(moment([2011, i, 1]).format('MMMM'), months.nominative[i], '1 ' + months.nominative[i]); + } + }); + + test('format month short case', function (assert) { + var monthsShort = { + 'nominative': 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'), + 'accusative': 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_') + }, i; + for (i = 0; i < 12; i++) { + assert.equal(moment([2011, i, 1]).format('D MMM'), '1 ' + monthsShort.accusative[i], '1 ' + monthsShort.accusative[i]); + assert.equal(moment([2011, i, 1]).format('MMM'), monthsShort.nominative[i], '1 ' + monthsShort.nominative[i]); + } + }); + + test('format month case with escaped symbols', function (assert) { + var months = { + 'nominative': 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_'), + 'accusative': 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_') + }, i; + for (i = 0; i < 12; i++) { + assert.equal(moment([2013, i, 1]).format('D[] MMMM'), '1 ' + months.accusative[i], '1 ' + months.accusative[i]); + assert.equal(moment([2013, i, 1]).format('[<i>]D[</i>] [<b>]MMMM[</b>]'), '<i>1</i> <b>' + months.accusative[i] + '</b>', '1 <b>' + months.accusative[i] + '</b>'); + assert.equal(moment([2013, i, 1]).format('D[-ին օրը] MMMM'), '1-ին օրը ' + months.accusative[i], '1-ին օրը ' + months.accusative[i]); + assert.equal(moment([2013, i, 1]).format('D, MMMM'), '1, ' + months.nominative[i], '1, ' + months.nominative[i]); + } + }); + + test('format month short case with escaped symbols', function (assert) { + var monthsShort = { + 'nominative': 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'), + 'accusative': 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_') + }, i; + for (i = 0; i < 12; i++) { + assert.equal(moment([2013, i, 1]).format('D[] MMM'), '1 ' + monthsShort.accusative[i], '1 ' + monthsShort.accusative[i]); + assert.equal(moment([2013, i, 1]).format('[<i>]D[</i>] [<b>]MMM[</b>]'), '<i>1</i> <b>' + monthsShort.accusative[i] + '</b>', '1 <b>' + monthsShort.accusative[i] + '</b>'); + assert.equal(moment([2013, i, 1]).format('D[-ին օրը] MMM'), '1-ին օրը ' + monthsShort.accusative[i], '1-ին օրը ' + monthsShort.accusative[i]); + assert.equal(moment([2013, i, 1]).format('D, MMM'), '1, ' + monthsShort.nominative[i], '1, ' + monthsShort.nominative[i]); + } + }); + + test('format week', function (assert) { + var expected = 'կիրակի կրկ կրկ_երկուշաբթի երկ երկ_երեքշաբթի երք երք_չորեքշաբթի չրք չրք_հինգշաբթի հնգ հնգ_ուրբաթ ուրբ ուրբ_շաբաթ շբթ շբթ'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'մի քանի վայրկյան', '44 seconds = seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'րոպե', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'րոպե', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 րոպե', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 րոպե', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ժամ', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ժամ', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 ժամ', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 ժամ', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 ժամ', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'օր', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'օր', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 օր', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'օր', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 օր', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 11}), true), '11 օր', '11 days = 11 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 21}), true), '21 օր', '21 days = 21 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 օր', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ամիս', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ամիս', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ամիս', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 ամիս', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 ամիս', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 ամիս', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ամիս', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 ամիս', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'տարի', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 տարի', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'տարի', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 տարի', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'մի քանի վայրկյան հետո', 'prefix'); + assert.equal(moment(0).from(30000), 'մի քանի վայրկյան առաջ', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'մի քանի վայրկյան հետո', 'in seconds'); + assert.equal(moment().add({d: 5}).fromNow(), '5 օր հետո', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'այսօր 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'այսօր 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'այսօր 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'վաղը 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'այսօր 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'երեկ 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + function makeFormat(d) { + return 'dddd [օրը ժամը] LT'; + } + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + function makeFormat(d) { + return '[անցած] dddd [օրը ժամը] LT'; + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-ին', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-ին', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2-րդ', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2-րդ', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3-րդ', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('id'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15.25.50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Minggu Min Mg_Senin Sen Sn_Selasa Sel Sl_Rabu Rab Rb_Kamis Kam Km_Jumat Jum Jm_Sabtu Sab Sb'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'beberapa detik', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'semenit', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'semenit', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 menit', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 menit', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'sejam', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'sejam', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 jam', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 jam', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 jam', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'sehari', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'sehari', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 hari', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'sehari', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 hari', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 hari', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'sebulan', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'sebulan', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'sebulan', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 bulan', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 bulan', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 bulan', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'sebulan', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 bulan', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'setahun', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 tahun', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'setahun', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 tahun', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'dalam beberapa detik', 'prefix'); + assert.equal(moment(0).from(30000), 'beberapa detik yang lalu', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'beberapa detik yang lalu', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'dalam beberapa detik', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'dalam 5 hari', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Hari ini pukul 02.00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Hari ini pukul 02.25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Hari ini pukul 03.00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Besok pukul 02.00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Hari ini pukul 01.00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Kemarin pukul 02.00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [pukul] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [pukul] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [pukul] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [lalu pukul] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [lalu pukul] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [lalu pukul] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('meridiem invariant', function (assert) { + var h, m, t1, t2; + for (h = 0; h < 24; ++h) { + for (m = 0; m < 60; m += 15) { + t1 = moment.utc([2000, 0, 1, h, m]); + t2 = moment(t1.format('A h:mm'), 'A h:mm'); + assert.equal(t2.format('HH:mm'), t1.format('HH:mm'), + 'meridiem at ' + t1.format('HH:mm')); + } + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('is'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'nokkrar sekúndur', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'mínúta', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'mínúta', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 mínútur', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 mínútur', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 21}), true), '21 mínúta', '21 minutes = 21 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'klukkustund', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'klukkustund', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 klukkustundir', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 klukkustundir', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 klukkustund', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'dagur', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'dagur', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dagar', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'dagur', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dagar', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dagar', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 11}), true), '11 dagar', '11 days = 11 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 21}), true), '21 dagur', '21 days = 21 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'mánuður', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'mánuður', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'mánuður', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mánuðir', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mánuðir', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mánuðir', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'mánuður', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mánuðir', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ár', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 ár', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ár', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 ár', '5 years = 5 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 21}), true), '21 ár', '21 years = 21 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'eftir nokkrar sekúndur', 'prefix'); + assert.equal(moment(0).from(30000), 'fyrir nokkrum sekúndum síðan', 'suffix'); + assert.equal(moment().subtract({m: 1}).fromNow(), 'fyrir mínútu síðan', 'a minute ago'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'fyrir nokkrum sekúndum síðan', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'eftir nokkrar sekúndur', 'in a few seconds'); + assert.equal(moment().add({m: 1}).fromNow(), 'eftir mínútu', 'in a minute'); + assert.equal(moment().add({d: 5}).fromNow(), 'eftir 5 daga', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'í dag kl. 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'í dag kl. 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'í dag kl. 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'á morgun kl. 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'í dag kl. 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'í gær kl. 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [kl.] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [kl.] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [kl.] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[síðasta] dddd [kl.] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.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); + assert.equal(m.calendar(), m.format('[síðasta] dddd [kl.] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('it'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Domenica Dom D_Lunedì Lun L_Martedì Mar Ma_Mercoledì Mer Me_Giovedì Gio G_Venerdì Ven V_Sabato Sab S'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'alcuni secondi', '44 seconds = seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'un minuto', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'un minuto', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuti', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuti', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'un\'ora', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'un\'ora', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 ore', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 ore', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 ore', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'un giorno', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'un giorno', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 giorni', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'un giorno', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 giorni', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 giorni', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'un mese', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'un mese', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'un mese', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mesi', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mesi', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mesi', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'un mese', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mesi', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'un anno', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 anni', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'un anno', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 anni', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'in alcuni secondi', 'prefix'); + assert.equal(moment(0).from(30000), 'alcuni secondi fa', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'in alcuni secondi', 'in seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'tra 5 giorni', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Oggi alle 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Oggi alle 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Oggi alle 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Domani alle 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Oggi alle 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Ieri alle 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [alle] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [alle] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [alle] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m, weekday, datestring; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + // Different date string + weekday = parseInt(m.format('d'), 10); + datestring = (weekday === 0) ? '[la scorsa] dddd [alle] LT' : '[lo scorso] dddd [alle] LT'; + assert.equal(m.calendar(), m.format(datestring), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(datestring), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(datestring), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52º', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1º', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1º', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2º', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2º', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ja'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '午後3時25分50秒'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = '日曜日 日 日_月曜日 月 月_火曜日 火 火_水曜日 水 水_木曜日 木 木_金曜日 金 金_土曜日 土 土'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), '数秒', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), '1分', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), '1分', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2分', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44分', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), '1時間', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), '1時間', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2時間', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5時間', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21時間', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), '1日', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), '1日', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2日', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), '1日', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5日', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25日', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), '1ヶ月', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), '1ヶ月', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), '1ヶ月', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2ヶ月', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2ヶ月', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3ヶ月', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), '1ヶ月', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5ヶ月', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), '1年', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2年', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), '1年', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5年', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), '数秒後', 'prefix'); + assert.equal(moment(0).from(30000), '数秒前', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), '数秒前', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), '数秒後', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), '5日後', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), '今日 午前2時0分', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), '今日 午前2時25分', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), '今日 午前3時0分', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), '明日 午前2時0分', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), '今日 午前1時0分', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), '昨日 午前2時0分', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('[来週]dddd LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[来週]dddd LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[来週]dddd LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[前週]dddd LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[前週]dddd LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[前週]dddd LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday format', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('jv'); + + + test('parse', function (assert) { + var tests = 'Januari Jan_Februari Feb_Maret Mar_April Apr_Mei Mei_Juni Jun_Juli Jul_Agustus Ags_September Sep_Oktober Okt_Nopember Nop_Desember Des'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Minggu, Februari 14 2010, 3:25:50 sonten'], + ['ddd, hA', 'Min, 3sonten'], + ['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', 'sonten sonten'], + ['[the] DDDo [day of the year]', 'the 45 day of the year'], + ['LTS', '15.25.50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format month', function (assert) { + var expected = 'Januari Jan_Februari Feb_Maret Mar_April Apr_Mei Mei_Juni Jun_Juli Jul_Agustus Ags_September Sep_Oktober Okt_Nopember Nop_Desember Des'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Minggu Min Mg_Senen Sen Sn_Seloso Sel Sl_Rebu Reb Rb_Kemis Kem Km_Jemuwah Jem Jm_Septu Sep Sp'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'sawetawis detik', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'setunggal menit', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'setunggal menit', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 menit', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 menit', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'setunggal jam', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'setunggal jam', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 jam', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 jam', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 jam', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'sedinten', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'sedinten', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dinten', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'sedinten', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dinten', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dinten', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'sewulan', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'sewulan', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'sewulan', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 wulan', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 wulan', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 wulan', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'sewulan', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 wulan', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'setaun', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 taun', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'setaun', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 taun', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'wonten ing sawetawis detik', 'prefix'); + assert.equal(moment(0).from(30000), 'sawetawis detik ingkang kepengker', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'sawetawis detik ingkang kepengker', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'wonten ing sawetawis detik', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'wonten ing 5 dinten', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Dinten puniko pukul 02.00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Dinten puniko pukul 02.25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Dinten puniko pukul 03.00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Mbenjang pukul 02.00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Dinten puniko pukul 01.00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Kala wingi pukul 02.00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [pukul] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [pukul] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [pukul] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [kepengker pukul] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [kepengker pukul] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [kepengker pukul] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('meridiem invariant', function (assert) { + var h, m, t1, t2; + for (h = 0; h < 24; ++h) { + for (m = 0; m < 60; m += 15) { + t1 = moment.utc([2000, 0, 1, h, m]); + t2 = moment(t1.format('A h:mm'), 'A h:mm'); + assert.equal(t2.format('HH:mm'), t1.format('HH:mm'), + 'meridiem at ' + t1.format('HH:mm')); + } + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ka'); + + test('parse', function (assert) { + var i, + tests = 'იანვარი იან_თებერვალი თებ_მარტი მარ_აპრილი აპრ_მაისი მაი_ივნისი ივნ_ივლისი ივლ_აგვისტო აგვ_სექტემბერი სექ_ოქტომბერი ოქტ_ნოემბერი ნოე_დეკემბერი დეკ'.split('_'); + + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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-ე დღე'], + ['LTS', '3:25:50 PM'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1-ლი', '1-ლი'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), 'მე-2', 'მე-2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), 'მე-3', 'მე-3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), 'მე-4', 'მე-4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), 'მე-5', 'მე-5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), 'მე-6', 'მე-6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), 'მე-7', 'მე-7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), 'მე-8', 'მე-8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), 'მე-9', 'მე-9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), 'მე-10', 'მე-10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), 'მე-11', 'მე-11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), 'მე-12', 'მე-12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), 'მე-13', 'მე-13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), 'მე-14', 'მე-14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), 'მე-15', 'მე-15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), 'მე-16', 'მე-16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), 'მე-17', 'მე-17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), 'მე-18', 'მე-18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), 'მე-19', 'მე-19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), 'მე-20', 'მე-20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21-ე', '21-ე'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22-ე', '22-ე'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23-ე', '23-ე'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24-ე', '24-ე'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25-ე', '25-ე'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26-ე', '26-ე'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27-ე', '27-ე'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28-ე', '28-ე'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29-ე', '29-ე'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30-ე', '30-ე'); + + assert.equal(moment('2011 40', 'YYYY DDD').format('DDDo'), 'მე-40', 'მე-40'); + assert.equal(moment('2011 50', 'YYYY DDD').format('DDDo'), '50-ე', '50-ე'); + assert.equal(moment('2011 60', 'YYYY DDD').format('DDDo'), 'მე-60', 'მე-60'); + assert.equal(moment('2011 100', 'YYYY DDD').format('DDDo'), 'მე-100', 'მე-100'); + assert.equal(moment('2011 101', 'YYYY DDD').format('DDDo'), '101-ე', '101-ე'); + }); + + test('format month', function (assert) { + var i, + expected = 'იანვარი იან_თებერვალი თებ_მარტი მარ_აპრილი აპრ_მაისი მაი_ივნისი ივნ_ივლისი ივლ_აგვისტო აგვ_სექტემბერი სექ_ოქტომბერი ოქტ_ნოემბერი ნოე_დეკემბერი დეკ'.split('_'); + + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var i, + expected = 'კვირა კვი კვ_ორშაბათი ორშ ორ_სამშაბათი სამ სა_ოთხშაბათი ოთხ ოთ_ხუთშაბათი ხუთ ხუ_პარასკევი პარ პა_შაბათი შაბ შა'.split('_'); + + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'რამდენიმე წამი', '44 წამი = რამდენიმე წამი'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'წუთი', '45 წამი = წუთი'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'წუთი', '89 წამი = წუთი'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 წუთი', '90 წამი = 2 წუთი'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 წუთი', '44 წამი = 44 წუთი'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'საათი', '45 წამი = საათი'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'საათი', '89 წამი = საათი'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 საათი', '90 წამი = 2 საათი'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 საათი', '5 საათი = 5 საათი'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 საათი', '21 საათი = 21 საათი'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'დღე', '22 საათი = დღე'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'დღე', '35 საათი = დღე'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 დღე', '36 საათი = 2 დღე'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'დღე', '1 დღე = დღე'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 დღე', '5 დღე = 5 დღე'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 დღე', '25 დღე = 25 დღე'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'თვე', '26 დღე = თვე'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'თვე', '30 დღე = თვე'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'თვე', '45 დღე = თვე'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 თვე', '46 დღე = 2 თვე'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 თვე', '75 დღე = 2 თვე'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 თვე', '76 დღე = 3 თვე'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'თვე', '1 თვე = თვე'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 თვე', '5 თვე = 5 თვე'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'წელი', '345 დღე = წელი'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 წელი', '548 დღე = 2 წელი'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'წელი', '1 წელი = წელი'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 წელი', '5 წელი = 5 წელი'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'რამდენიმე წამში', 'ში სუფიქსი'); + assert.equal(moment(0).from(30000), 'რამდენიმე წამის წინ', 'წინ სუფიქსი'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'რამდენიმე წამის წინ', 'უნდა აჩვენოს როგორც წარსული'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'რამდენიმე წამში', 'რამდენიმე წამში'); + assert.equal(moment().add({d: 5}).fromNow(), '5 დღეში', '5 დღეში'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'დღეს 2:00 AM-ზე', 'დღეს ამავე დროს'); + assert.equal(moment(a).add({m: 25}).calendar(), 'დღეს 2:25 AM-ზე', 'ახლანდელ დროს დამატებული 25 წუთი'); + assert.equal(moment(a).add({h: 1}).calendar(), 'დღეს 3:00 AM-ზე', 'ახლანდელ დროს დამატებული 1 საათი'); + assert.equal(moment(a).add({d: 1}).calendar(), 'ხვალ 2:00 AM-ზე', 'ხვალ ამავე დროს'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'დღეს 1:00 AM-ზე', 'ახლანდელ დროს გამოკლებული 1 საათი'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'გუშინ 2:00 AM-ზე', 'გუშინ ამავე დროს'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('[შემდეგ] dddd LT[-ზე]'), 'დღეს + ' + i + ' დღე ახლანდელ დროს'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[შემდეგ] dddd LT[-ზე]'), 'დღეს + ' + i + ' დღე დღის დასაწყისში'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[შემდეგ] dddd LT[-ზე]'), 'დღეს + ' + i + ' დღე დღის დასასრულს'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[წინა] dddd LT[-ზე]'), 'დღეს - ' + i + ' დღე ახლანდელ დროს'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[წინა] dddd LT[-ზე]'), 'დღეს - ' + i + ' დღე დღის დასაწყისში'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[წინა] dddd LT[-ზე]'), 'დღეს - ' + i + ' დღე დღის დასასრულს'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 კვირის წინ'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), '1 კვირაში'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 კვირის წინ'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), '2 კვირაში'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'დეკ 26 2011 უნდა იყოს კვირა 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'იან 1 2012 უნდა იყოს კვირა 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'იან 2 2012 უნდა იყოს კვირა 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'იან 8 2012 უნდა იყოს კვირა 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'იან 9 2012 უნდა იყოს კვირა 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'იან 1 2007 უნდა იყოს კვირა 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'იან 7 2007 უნდა იყოს კვირა 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'იან 8 2007 უნდა იყოს კვირა 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'იან 14 2007 უნდა იყოს კვირა 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'იან 15 2007 უნდა იყოს კვირა 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'დეკ 31 2007 უნდა იყოს კვირა 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'იან 1 2008 უნდა იყოს კვირა 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'იან 6 2008 უნდა იყოს კვირა 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'იან 7 2008 უნდა იყოს კვირა 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'იან 13 2008 უნდა იყოს კვირა 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'იან 14 2008 უნდა იყოს კვირა 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'დეკ 30 2002 უნდა იყოს კვირა 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'იან 1 2003 უნდა იყოს კვირა 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'იან 5 2003 უნდა იყოს კვირა 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'იან 6 2003 უნდა იყოს კვირა 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'იან 12 2003 უნდა იყოს კვირა 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'იან 13 2003 უნდა იყოს კვირა 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'დეკ 29 2008 უნდა იყოს კვირა 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'იან 1 2009 უნდა იყოს კვირა 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'იან 4 2009 უნდა იყოს კვირა 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'იან 5 2009 უნდა იყოს კვირა 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'იან 11 2009 უნდა იყოს კვირა 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'იან 12 2009 უნდა იყოს კვირა 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'დეკ 28 2009 უნდა იყოს კვირა 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'იან 1 2010 უნდა იყოს კვირა 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'იან 3 2010 უნდა იყოს კვირა 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'იან 4 2010 უნდა იყოს კვირა 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'იან 10 2010 უნდა იყოს კვირა 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'იან 11 2010 უნდა იყოს კვირა 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'დეკ 27 2010 უნდა იყოს კვირა 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'იან 1 2011 უნდა იყოს კვირა 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'იან 2 2011 უნდა იყოს კვირა 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'იან 3 2011 უნდა იყოს კვირა 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'იან 9 2011 უნდა იყოს კვირა 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'იან 10 2011 უნდა იყოს კვირა 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-ლი', 'დეკ 26 2011 უნდა იყოს კვირა 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-ლი', 'იან 1 2012 უნდა იყოს კვირა 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 მე-2', 'იან 2 2012 უნდა იყოს კვირა 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 მე-2', 'იან 8 2012 უნდა იყოს კვირა 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 მე-3', 'იან 9 2012 უნდა იყოს კვირა 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('km'); + + test('parse', function (assert) { + var tests = 'មករា មករា_កុម្ភៈ កុម្ភៈ_មិនា មិនា_មេសា មេសា_ឧសភា ឧសភា_មិថុនា មិថុនា_កក្កដា កក្កដា_សីហា សីហា_កញ្ញា កញ្ញា_តុលា តុលា_វិច្ឆិកា វិច្ឆិកា_ធ្នូ ធ្នូ'.split('_'), + i; + + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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', '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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1st'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2nd'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3rd'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4th'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5th'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6th'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7th'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8th'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9th'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10th'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11th'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12th'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13th'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14th'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15th'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16th'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17th'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18th'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19th'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20th'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21st'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22nd'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23rd'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24th'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25th'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26th'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27th'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28th'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29th'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30th'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31st'); + }); + + test('format month', function (assert) { + var expected = 'មករា មករា_កុម្ភៈ កុម្ភៈ_មិនា មិនា_មេសា មេសា_ឧសភា ឧសភា_មិថុនា មិថុនា_កក្កដា កក្កដា_សីហា សីហា_កញ្ញា កញ្ញា_តុលា តុលា_វិច្ឆិកា វិច្ឆិកា_ធ្នូ ធ្នូ'.split('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'អាទិត្យ អាទិត្យ អាទិត្យ_ច័ន្ទ ច័ន្ទ ច័ន្ទ_អង្គារ អង្គារ អង្គារ_ពុធ ពុធ ពុធ_ព្រហស្បតិ៍ ព្រហស្បតិ៍ ព្រហស្បតិ៍_សុក្រ សុក្រ សុក្រ_សៅរ៍ សៅរ៍ សៅរ៍'.split('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'ប៉ុន្មានវិនាទី', '44 seconds = ប៉ុន្មានវិនាទី'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'មួយនាទី', '45 seconds = មួយនាទី'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'មួយនាទី', '89 seconds = មួយនាទី'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 នាទី', '90 seconds = 2 នាទី'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 នាទី', '44 minutes = 44 នាទី'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'មួយម៉ោង', '45 minutes = មួយម៉ោង'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'មួយម៉ោង', '89 minutes = មួយម៉ោង'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 ម៉ោង', '90 minutes = 2 ម៉ោង'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 ម៉ោង', '5 hours = 5 ម៉ោង'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 ម៉ោង', '21 hours = 21 ម៉ោង'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'មួយថ្ងៃ', '22 hours = មួយថ្ងៃ'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'មួយថ្ងៃ', '35 hours = មួយថ្ងៃ'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 ថ្ងៃ', '36 hours = 2 ថ្ងៃ'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'មួយថ្ងៃ', '1 day = មួយថ្ងៃ'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 ថ្ងៃ', '5 days = 5 ថ្ងៃ'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 ថ្ងៃ', '25 days = 25 ថ្ងៃ'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'មួយខែ', '26 days = មួយខែ'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'មួយខែ', '30 days = មួយខែ'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'មួយខែ', '43 days = មួយខែ'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 ខែ', '46 days = 2 ខែ'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 ខែ', '75 days = 2 ខែ'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 ខែ', '76 days = 3 ខែ'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'មួយខែ', '1 month = មួយខែ'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 ខែ', '5 months = 5 ខែ'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'មួយឆ្នាំ', '345 days = មួយឆ្នាំ'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 ឆ្នាំ', '548 days = 2 ឆ្នាំ'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'មួយឆ្នាំ', '1 year = មួយឆ្នាំ'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 ឆ្នាំ', '5 years = 5 ឆ្នាំ'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'ប៉ុន្មានវិនាទីទៀត', 'prefix'); + assert.equal(moment(0).from(30000), 'ប៉ុន្មានវិនាទីមុន', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'ប៉ុន្មានវិនាទីមុន', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({ + s: 30 + }).fromNow(), 'ប៉ុន្មានវិនាទីទៀត', 'in a few seconds'); + assert.equal(moment().add({ + d: 5 + }).fromNow(), '5 ថ្ងៃទៀត', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'ថ្ងៃនៈ ម៉ោង 02:00', 'today at the same time'); + assert.equal(moment(a).add({ + m: 25 + }).calendar(), 'ថ្ងៃនៈ ម៉ោង 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({ + h: 1 + }).calendar(), 'ថ្ងៃនៈ ម៉ោង 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({ + d: 1 + }).calendar(), 'ស្អែក ម៉ោង 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({ + h: 1 + }).calendar(), 'ថ្ងៃនៈ ម៉ោង 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({ + d: 1 + }).calendar(), 'ម្សិលមិញ ម៉ោង 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({ + d: i + }); + assert.equal(m.calendar(), m.format('dddd [ម៉ោង] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [ម៉ោង] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [ម៉ោង] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ + d: i + }); + assert.equal(m.calendar(), m.format('dddd [សប្តាហ៍មុន] [ម៉ោង] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [សប្តាហ៍មុន] [ម៉ោង] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [សប្តាហ៍មុន] [ម៉ោង] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({ + w: 1 + }), + weeksFromNow = moment().add({ + w: 1 + }); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({ + w: 2 + }); + weeksFromNow = moment().add({ + w: 2 + }); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ko'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('parse meridiem', function (assert) { + var elements = [{ + expression : '1981년 9월 8일 오후 2시 30분', + inputFormat : 'YYYY[년] M[월] D[일] A h[시] m[분]', + outputFormat : 'A', + expected : '오후' + }, { + expression : '1981년 9월 8일 오전 2시 30분', + inputFormat : 'YYYY[년] M[월] D[일] A h[시] m[분]', + outputFormat : 'A h시', + expected : '오전 2시' + }, { + expression : '14시 30분', + inputFormat : 'H[시] m[분]', + outputFormat : 'A', + expected : '오후' + }, { + expression : '오후 4시', + inputFormat : 'A h[시]', + outputFormat : 'H', + expected : '16' + }], i, l, it, actual; + + + for (i = 0, l = elements.length; i < l; ++i) { + it = elements[i]; + actual = moment(it.expression, it.inputFormat).format(it.outputFormat); + + assert.equal( + actual, + it.expected, + '\'' + it.outputFormat + '\' of \'' + it.expression + '\' must be \'' + it.expected + '\' but was \'' + actual + '\'.' + ); + } + }); + + test('format', function (assert) { + 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일째 되는 날'], + ['LTS', '오후 3시 25분 50초'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1일', '1일'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2일', '2일'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3일', '3일'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4일', '4일'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5일', '5일'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6일', '6일'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7일', '7일'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8일', '8일'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9일', '9일'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10일', '10일'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11일', '11일'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12일', '12일'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13일', '13일'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14일', '14일'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15일', '15일'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16일', '16일'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17일', '17일'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18일', '18일'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19일', '19일'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20일', '20일'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21일', '21일'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22일', '22일'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23일', '23일'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24일', '24일'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25일', '25일'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26일', '26일'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27일', '27일'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28일', '28일'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29일', '29일'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30일', '30일'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31일', '31일'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = '일요일 일 일_월요일 월 월_화요일 화 화_수요일 수 수_목요일 목 목_금요일 금 금_토요일 토 토'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), '몇초', '44초 = 몇초'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), '일분', '45초 = 일분'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), '일분', '89초 = 일분'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2분', '90초 = 2분'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44분', '44분 = 44분'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), '한시간', '45분 = 한시간'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), '한시간', '89분 = 한시간'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2시간', '90분 = 2시간'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5시간', '5시간 = 5시간'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21시간', '21시간 = 21시간'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), '하루', '22시간 = 하루'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), '하루', '35시간 = 하루'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2일', '36시간 = 2일'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), '하루', '하루 = 하루'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5일', '5일 = 5일'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25일', '25일 = 25일'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), '한달', '26일 = 한달'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), '한달', '30일 = 한달'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), '한달', '45일 = 한달'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2달', '46일 = 2달'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2달', '75일 = 2달'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3달', '76일 = 3달'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), '한달', '1달 = 한달'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5달', '5달 = 5달'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), '일년', '345일 = 일년'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2년', '548일 = 2년'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), '일년', '일년 = 일년'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5년', '5년 = 5년'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), '몇초 후', 'prefix'); + assert.equal(moment(0).from(30000), '몇초 전', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), '몇초 전', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), '몇초 후', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), '5일 후', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), '오늘 오전 2시 0분', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), '오늘 오전 2시 25분', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), '오늘 오전 3시 0분', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), '내일 오전 2시 0분', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), '오늘 오전 1시 0분', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), '어제 오전 2시 0분', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('지난주 dddd LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('지난주 dddd LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('지난주 dddd LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday format', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1일', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1일', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2일', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2일', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3일', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('lb'); + + test('parse', function (assert) { + var tests = 'Januar Jan._Februar Febr._Mäerz Mrz._Abrëll Abr._Mee Mee_Juni Jun._Juli Jul._August Aug._September Sept._Oktober Okt._November Nov._Dezember Dez.'.split('_'), i; + + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, Do MMMM YYYY, HH:mm:ss', 'Sonndeg, 14. Februar 2010, 15:25:50'], + ['ddd, HH:mm', 'So., 15:25'], + ['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. Sonndeg 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'], + ['LTS', '15:25:50 Auer'], + ['L', '14.02.2010'], + ['LL', '14. Februar 2010'], + ['LLL', '14. Februar 2010 15:25 Auer'], + ['LLLL', 'Sonndeg, 14. Februar 2010 15:25 Auer'], + ['l', '14.2.2010'], + ['ll', '14. Febr. 2010'], + ['lll', '14. Febr. 2010 15:25 Auer'], + ['llll', 'So., 14. Febr. 2010 15:25 Auer'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format month', function (assert) { + var expected = 'Januar Jan._Februar Febr._Mäerz Mrz._Abrëll Abr._Mee Mee_Juni Jun._Juli Jul._August Aug._September Sept._Oktober Okt._November Nov._Dezember Dez.'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Sonndeg So. So_Méindeg Mé. Mé_Dënschdeg Dë. Dë_Mëttwoch Më. Më_Donneschdeg Do. Do_Freideg Fr. Fr_Samschdeg Sa. Sa'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'e puer Sekonnen', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'eng Minutt', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'eng Minutt', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 Minutten', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 Minutten', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'eng Stonn', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'eng Stonn', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 Stonnen', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 Stonnen', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 Stonnen', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'een Dag', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'een Dag', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 Deeg', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'een Dag', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 Deeg', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 Deeg', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ee Mount', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ee Mount', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ee Mount', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 Méint', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 Méint', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 Méint', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ee Mount', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 Méint', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ee Joer', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 Joer', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ee Joer', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 Joer', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'an e puer Sekonnen', 'prefix'); + assert.equal(moment(0).from(30000), 'virun e puer Sekonnen', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'an e puer Sekonnen', 'in a few seconds'); + assert.equal(moment().add({d: 1}).fromNow(), 'an engem Dag', 'in one day'); + assert.equal(moment().add({d: 2}).fromNow(), 'an 2 Deeg', 'in 2 days'); + assert.equal(moment().add({d: 3}).fromNow(), 'an 3 Deeg', 'in 3 days'); + assert.equal(moment().add({d: 4}).fromNow(), 'a 4 Deeg', 'in 4 days'); + assert.equal(moment().add({d: 5}).fromNow(), 'a 5 Deeg', 'in 5 days'); + assert.equal(moment().add({d: 6}).fromNow(), 'a 6 Deeg', 'in 6 days'); + assert.equal(moment().add({d: 7}).fromNow(), 'a 7 Deeg', 'in 7 days'); + assert.equal(moment().add({d: 8}).fromNow(), 'an 8 Deeg', 'in 8 days'); + assert.equal(moment().add({d: 9}).fromNow(), 'an 9 Deeg', 'in 9 days'); + assert.equal(moment().add({d: 10}).fromNow(), 'an 10 Deeg', 'in 10 days'); + assert.equal(moment().add({y: 100}).fromNow(), 'an 100 Joer', 'in 100 years'); + assert.equal(moment().add({y: 400}).fromNow(), 'a 400 Joer', 'in 400 years'); + }); + + test('calendar last week', function (assert) { + var i, m, weekday, datestring; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + + // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) + weekday = parseInt(m.format('d'), 10); + datestring = (weekday === 2 || weekday === 4 ? '[Leschten] dddd [um] LT' : '[Leschte] dddd [um] LT'); + + assert.equal(m.calendar(), m.format(datestring), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(datestring), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(datestring), 'Today + ' + i + ' days end of day'); + } + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('lt'); + + test('parse', function (assert) { + var tests = 'sausio sau_vasario vas_kovo kov_balandžio bal_gegužės geg_birželio bir_liepos lie_rugpjūčio rgp_rugsėjo rgs_spalio spa_lapkričio lap_gruodžio grd'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, Do MMMM YYYY, h:mm:ss a', 'sekmadienis, 14-oji vasario 2010, 3:25:50 pm'], + ['ddd, hA', 'Sek, 3PM'], + ['M Mo MM MMMM MMM', '2 2-oji 02 vasario vas'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14-oji 14'], + ['d do dddd ddd dd', '0 0-oji sekmadienis Sek S'], + ['DDD DDDo DDDD', '45 45-oji 045'], + ['w wo ww', '6 6-oji 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'pm PM'], + ['DDDo [metų diena]', '45-oji metų diena'], + ['LTS', '15:25:50'], + ['L', '2010-02-14'], + ['LL', '2010 m. vasario 14 d.'], + ['LLL', '2010 m. vasario 14 d., 15:25 val.'], + ['LLLL', '2010 m. vasario 14 d., sekmadienis, 15:25 val.'], + ['l', '2010-02-14'], + ['ll', '2010 m. vasario 14 d.'], + ['lll', '2010 m. vasario 14 d., 15:25 val.'], + ['llll', '2010 m. vasario 14 d., Sek, 15:25 val.'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1-oji', '1-oji'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2-oji', '2-oji'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3-oji', '3-oji'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4-oji', '4-oji'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5-oji', '5-oji'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6-oji', '6-oji'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7-oji', '7-oji'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8-oji', '8-oji'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9-oji', '9-oji'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10-oji', '10-oji'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11-oji', '11-oji'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12-oji', '12-oji'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13-oji', '13-oji'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14-oji', '14-oji'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15-oji', '15-oji'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16-oji', '16-oji'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17-oji', '17-oji'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18-oji', '18-oji'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19-oji', '19-oji'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20-oji', '20-oji'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21-oji', '21-oji'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22-oji', '22-oji'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23-oji', '23-oji'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24-oji', '24-oji'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25-oji', '25-oji'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26-oji', '26-oji'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27-oji', '27-oji'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28-oji', '28-oji'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29-oji', '29-oji'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30-oji', '30-oji'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31-oji', '31-oji'); + }); + + test('format month', function (assert) { + var expected = 'sausio sau_vasario vas_kovo kov_balandžio bal_gegužės geg_birželio bir_liepos lie_rugpjūčio rgp_rugsėjo rgs_spalio spa_lapkričio lap_gruodžio grd'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'sekmadienis Sek S_pirmadienis Pir P_antradienis Ant A_trečiadienis Tre T_ketvirtadienis Ket K_penktadienis Pen Pn_šeštadienis Šeš Š'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('format week on US calendar', function (assert) { + // Tests, whether the weekday names are correct, even if the week does not start on Monday + moment.locale('lt', {week: {dow: 0, doy: 6}}); + var expected = 'sekmadienis Sek S_pirmadienis Pir P_antradienis Ant A_trečiadienis Tre T_ketvirtadienis Ket K_penktadienis Pen Pn_šeštadienis Šeš Š'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + moment.locale('lt', {week: {dow: 1, doy: 4}}); + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'kelios sekundės', '44 seconds = seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'minutė', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'minutė', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutės', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 10}), true), '10 minučių', '10 minutes = 10 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 11}), true), '11 minučių', '11 minutes = 11 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 19}), true), '19 minučių', '19 minutes = 19 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 20}), true), '20 minučių', '20 minutes = 20 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutės', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'valanda', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'valanda', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 valandos', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 valandos', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 10}), true), '10 valandų', '10 hours = 10 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 valandos', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'diena', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'diena', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dienos', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'diena', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dienos', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 10}), true), '10 dienų', '10 days = 10 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dienos', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'mėnuo', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'mėnuo', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'mėnuo', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mėnesiai', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mėnesiai', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mėnesiai', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'mėnuo', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mėnesiai', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 10}), true), '10 mėnesių', '10 months = 10 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'metai', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 metai', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'metai', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 metai', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'po kelių sekundžių', 'prefix'); + assert.equal(moment(0).from(30000), 'prieš kelias sekundes', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'prieš kelias sekundes', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'po kelių sekundžių', 'in seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'po 5 dienų', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Šiandien 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Šiandien 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Šiandien 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Rytoj 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Šiandien 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Vakar 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[Praėjusį] dddd LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[Praėjusį] dddd LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[Praėjusį] dddd LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52-oji', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1-oji', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1-oji', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2-oji', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2-oji', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('lv'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + // Includes testing the cases of withoutSuffix = true and false. + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'dažas sekundes', '44 seconds = seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), false), 'pirms dažām sekundēm', '44 seconds with suffix = seconds ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'minūte', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), false), 'pirms minūtes', '45 seconds with suffix = a minute ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'minūte', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: -89}), false), 'pēc minūtes', '89 seconds with suffix/prefix = in a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minūtes', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), false), 'pirms 2 minūtēm', '90 seconds with suffix = 2 minutes ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minūtes', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), false), 'pirms 44 minūtēm', '44 minutes with suffix = 44 minutes ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'stunda', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), false), 'pirms stundas', '45 minutes with suffix = an hour ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'stunda', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 stundas', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: -90}), false), 'pēc 2 stundām', '90 minutes with suffix = in 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 stundas', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), false), 'pirms 5 stundām', '5 hours with suffix = 5 hours ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 stunda', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), false), 'pirms 21 stundas', '21 hours with suffix = 21 hours ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'diena', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), false), 'pirms dienas', '22 hours with suffix = a day ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'diena', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dienas', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), false), 'pirms 2 dienām', '36 hours with suffix = 2 days ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'diena', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dienas', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), false), 'pirms 5 dienām', '5 days with suffix = 5 days ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dienas', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), false), 'pirms 25 dienām', '25 days with suffix = 25 days ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'mēnesis', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), false), 'pirms mēneša', '26 days with suffix = a month ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'mēnesis', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'mēnesis', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mēneši', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), false), 'pirms 2 mēnešiem', '46 days with suffix = 2 months ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mēneši', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mēneši', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), false), 'pirms 3 mēnešiem', '76 days with suffix = 3 months ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'mēnesis', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mēneši', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), false), 'pirms 5 mēnešiem', '5 months with suffix = 5 months ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'gads', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), false), 'pirms gada', '345 days with suffix = a year ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 gadi', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), false), 'pirms 2 gadiem', '548 days with suffix = 2 years ago'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'gads', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 gadi', '5 years = 5 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), false), 'pirms 5 gadiem', '5 years with suffix = 5 years ago'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'pēc dažām sekundēm', 'prefix'); + assert.equal(moment(0).from(30000), 'pirms dažām sekundēm', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'pirms dažām sekundēm', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'pēc dažām sekundēm', 'in seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'pēc 5 dienām', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Šodien pulksten 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Šodien pulksten 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Šodien pulksten 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Rīt pulksten 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Šodien pulksten 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Vakar pulksten 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [pulksten] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [pulksten] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [pulksten] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[Pagājušā] dddd [pulksten] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.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); + assert.equal(m.calendar(), m.format('[Pagājušā] dddd [pulksten] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('me'); + + test('parse', function (assert) { + var tests = 'januar jan._februar feb._mart mar._april apr._maj maj_jun jun_jul jul_avgust avg._septembar sep._oktobar okt._novembar nov._decembar dec.'.split('_'), + i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, Do MMMM YYYY, h:mm:ss a', 'nedjelja, 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. nedjelja 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'], + ['LTS', '15:25:50'], + ['L', '14. 02. 2010'], + ['LL', '14. februar 2010'], + ['LLL', '14. februar 2010 15:25'], + ['LLLL', 'nedjelja, 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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + var expected = 'januar jan._februar feb._mart mar._april apr._maj maj_jun jun_jul jul_avgust avg._septembar sep._oktobar okt._novembar nov._decembar dec.'.split('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'nedjelja ned. ne_ponedjeljak pon. po_utorak uto. ut_srijeda sri. sr_četvrtak čet. če_petak pet. pe_subota sub. su'.split('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'nekoliko sekundi', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'jedan minut', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'jedan minut', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuta', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuta', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'jedan sat', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'jedan sat', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 sata', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 sati', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 sati', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'dan', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'dan', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dana', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'dan', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dana', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dana', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'mjesec', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'mjesec', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'mjesec', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mjeseca', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mjeseca', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mjeseca', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'mjesec', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mjeseci', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'godinu', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 godine', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'godinu', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 godina', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'za nekoliko sekundi', 'prefix'); + assert.equal(moment(0).from(30000), 'prije nekoliko sekundi', 'prefix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'prije nekoliko sekundi', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'za nekoliko sekundi', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'za 5 dana', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'danas u 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'danas u 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'danas u 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'sjutra u 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'danas u 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'juče u 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + function makeFormat(d) { + var lastWeekDay = [ + '[prošle] [nedjelje] [u] LT', + '[prošlog] [ponedjeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srijede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + + return lastWeekDay[d.day()]; + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + // Monday is the first day of the week. + // The week that contains Jan 1st is the first week of the year. + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1.', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1.', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2.', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2.', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3.', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('mk'); + + test('parse', function (assert) { + var tests = 'јануари јан_февруари фев_март мар_април апр_мај мај_јуни јун_јули јул_август авг_септември сеп_октомври окт_ноември ное_декември дек'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, H: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-ев недела нед нe'], + ['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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1-ви', '1-ви'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2-ри', '2-ри'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3-ти', '3-ти'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4-ти', '4-ти'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5-ти', '5-ти'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6-ти', '6-ти'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7-ми', '7-ми'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8-ми', '8-ми'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9-ти', '9-ти'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10-ти', '10-ти'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11-ти', '11-ти'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12-ти', '12-ти'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13-ти', '13-ти'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14-ти', '14-ти'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15-ти', '15-ти'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16-ти', '16-ти'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17-ти', '17-ти'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18-ти', '18-ти'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19-ти', '19-ти'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20-ти', '20-ти'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21-ви', '21-ви'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22-ри', '22-ри'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23-ти', '23-ти'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24-ти', '24-ти'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25-ти', '25-ти'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26-ти', '26-ти'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27-ми', '27-ми'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28-ми', '28-ми'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29-ти', '29-ти'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30-ти', '30-ти'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31-ви', '31-ви'); + }); + + test('format month', function (assert) { + var expected = 'јануари јан_февруари фев_март мар_април апр_мај мај_јуни јун_јули јул_август авг_септември сеп_октомври окт_ноември ное_декември дек'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'недела нед нe_понеделник пон пo_вторник вто вт_среда сре ср_четврток чет че_петок пет пе_сабота саб сa'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'неколку секунди', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'минута', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'минута', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 минути', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 минути', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'час', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'час', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 часа', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 часа', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 часа', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'ден', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'ден', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 дена', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'ден', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 дена', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 дена', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'месец', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'месец', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'месец', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 месеци', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 месеци', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 месеци', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'месец', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 месеци', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'година', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 години', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'година', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 години', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'после неколку секунди', 'prefix'); + assert.equal(moment(0).from(30000), 'пред неколку секунди', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'пред неколку секунди', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'после неколку секунди', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'после 5 дена', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Денес во 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Денес во 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Денес во 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Утре во 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Денес во 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Вчера во 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [во] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [во] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [во] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, 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}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-ви', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-ви', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2-ри', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2-ри', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3-ти', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ml'); + + test('parse', function (assert) { + var tests = 'ജനുവരി ജനു._ഫെബ്രുവരി ഫെബ്രു._മാർച്ച് മാർ._ഏപ്രിൽ ഏപ്രി._മേയ് മേയ്_ജൂൺ ജൂൺ_ജൂലൈ ജൂലൈ._ഓഗസ്റ്റ് ഓഗ._സെപ്റ്റംബർ സെപ്റ്റ._ഒക്ടോബർ ഒക്ടോ._നവംബർ നവം._ഡിസംബർ ഡിസം.'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, Do MMMM YYYY, a h:mm:ss -നു', 'ഞായറാഴ്ച, 14 ഫെബ്രുവരി 2010, ഉച്ച കഴിഞ്ഞ് 3:25:50 -നു'], + ['ddd, a h -നു', 'ഞായർ, ഉച്ച കഴിഞ്ഞ് 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', 'ഉച്ച കഴിഞ്ഞ് ഉച്ച കഴിഞ്ഞ്'], + ['LTS', 'ഉച്ച കഴിഞ്ഞ് 3:25:50 -നു'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + }); + + test('format month', function (assert) { + var expected = 'ജനുവരി ജനു._ഫെബ്രുവരി ഫെബ്രു._മാർച്ച് മാർ._ഏപ്രിൽ ഏപ്രി._മേയ് മേയ്_ജൂൺ ജൂൺ_ജൂലൈ ജൂലൈ._ഓഗസ്റ്റ് ഓഗ._സെപ്റ്റംബർ സെപ്റ്റ._ഒക്ടോബർ ഒക്ടോ._നവംബർ നവം._ഡിസംബർ ഡിസം.'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'ഞായറാഴ്ച ഞായർ ഞാ_തിങ്കളാഴ്ച തിങ്കൾ തി_ചൊവ്വാഴ്ച ചൊവ്വ ചൊ_ബുധനാഴ്ച ബുധൻ ബു_വ്യാഴാഴ്ച വ്യാഴം വ്യാ_വെള്ളിയാഴ്ച വെള്ളി വെ_ശനിയാഴ്ച ശനി ശ'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'അൽപ നിമിഷങ്ങൾ', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'ഒരു മിനിറ്റ്', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'ഒരു മിനിറ്റ്', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 മിനിറ്റ്', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 മിനിറ്റ്', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ഒരു മണിക്കൂർ', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ഒരു മണിക്കൂർ', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 മണിക്കൂർ', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 മണിക്കൂർ', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 മണിക്കൂർ', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'ഒരു ദിവസം', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'ഒരു ദിവസം', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 ദിവസം', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'ഒരു ദിവസം', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 ദിവസം', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 ദിവസം', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ഒരു മാസം', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ഒരു മാസം', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ഒരു മാസം', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 മാസം', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 മാസം', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 മാസം', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ഒരു മാസം', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 മാസം', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ഒരു വർഷം', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 വർഷം', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ഒരു വർഷം', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 വർഷം', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'അൽപ നിമിഷങ്ങൾ കഴിഞ്ഞ്', 'prefix'); + assert.equal(moment(0).from(30000), 'അൽപ നിമിഷങ്ങൾ മുൻപ്', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'അൽപ നിമിഷങ്ങൾ മുൻപ്', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'അൽപ നിമിഷങ്ങൾ കഴിഞ്ഞ്', 'അൽപ നിമിഷങ്ങൾ കഴിഞ്ഞ്'); + assert.equal(moment().add({d: 5}).fromNow(), '5 ദിവസം കഴിഞ്ഞ്', '5 ദിവസം കഴിഞ്ഞ്'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'ഇന്ന് രാത്രി 2:00 -നു', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'ഇന്ന് രാത്രി 2:25 -നു', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 3}).calendar(), 'ഇന്ന് രാവിലെ 5:00 -നു', 'Now plus 3 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'നാളെ രാത്രി 2:00 -നു', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'ഇന്ന് രാത്രി 1:00 -നു', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'ഇന്നലെ രാത്രി 2:00 -നു', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd[,] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd[,] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd[,] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[കഴിഞ്ഞ] dddd[,] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[കഴിഞ്ഞ] dddd[,] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[കഴിഞ്ഞ] dddd[,] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('meridiem', function (assert) { + assert.equal(moment([2011, 2, 23, 2, 30]).format('a'), 'രാത്രി', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('a'), 'രാവിലെ', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('a'), 'ഉച്ച കഴിഞ്ഞ്', 'during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('a'), 'വൈകുന്നേരം', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('a'), 'വൈകുന്നേരം', 'late evening'); + assert.equal(moment([2011, 2, 23, 21, 20]).format('a'), 'രാത്രി', 'night'); + + assert.equal(moment([2011, 2, 23, 2, 30]).format('A'), 'രാത്രി', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('A'), 'രാവിലെ', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('A'), 'ഉച്ച കഴിഞ്ഞ്', ' during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('A'), 'വൈകുന്നേരം', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('A'), 'വൈകുന്നേരം', 'late evening'); + assert.equal(moment([2011, 2, 23, 21, 20]).format('A'), 'രാത്രി', 'night'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('mr'); + + test('parse', function (assert) { + var tests = 'जानेवारी जाने._फेब्रुवारी फेब्रु._मार्च मार्च._एप्रिल एप्रि._मे मे._जून जून._जुलै जुलै._ऑगस्ट ऑग._सप्टेंबर सप्टें._ऑक्टोबर ऑक्टो._नोव्हेंबर नोव्हें._डिसेंबर डिसें.'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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', 'दुपारी दुपारी'], + ['LTS', 'दुपारी ३:२५:५० वाजता'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '१', '१'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '२', '२'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '३', '३'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '४', '४'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '५', '५'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '६', '६'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '७', '७'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '८', '८'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '९', '९'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '१०', '१०'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '११', '११'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '१२', '१२'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '१३', '१३'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '१४', '१४'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '१५', '१५'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '१६', '१६'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '१७', '१७'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '१८', '१८'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '१९', '१९'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '२०', '२०'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '२१', '२१'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '२२', '२२'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '२३', '२३'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '२४', '२४'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '२५', '२५'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '२६', '२६'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '२७', '२७'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '२८', '२८'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '२९', '२९'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '३०', '३०'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '३१', '३१'); + }); + + test('format month', function (assert) { + var expected = 'जानेवारी जाने._फेब्रुवारी फेब्रु._मार्च मार्च._एप्रिल एप्रि._मे मे._जून जून._जुलै जुलै._ऑगस्ट ऑग._सप्टेंबर सप्टें._ऑक्टोबर ऑक्टो._नोव्हेंबर नोव्हें._डिसेंबर डिसें.'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'रविवार रवि र_सोमवार सोम सो_मंगळवार मंगळ मं_बुधवार बुध बु_गुरूवार गुरू गु_शुक्रवार शुक्र शु_शनिवार शनि श'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'सेकंद', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'एक मिनिट', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'एक मिनिट', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '२ मिनिटे', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '४४ मिनिटे', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'एक तास', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'एक तास', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '२ तास', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '५ तास', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '२१ तास', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'एक दिवस', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'एक दिवस', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '२ दिवस', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'एक दिवस', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '५ दिवस', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '२५ दिवस', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'एक महिना', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'एक महिना', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'एक महिना', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '२ महिने', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '२ महिने', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '३ महिने', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'एक महिना', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '५ महिने', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'एक वर्ष', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '२ वर्षे', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'एक वर्ष', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '५ वर्षे', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'सेकंद नंतर', 'prefix'); + assert.equal(moment(0).from(30000), 'सेकंद पूर्वी', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'सेकंद पूर्वी', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'सेकंद नंतर', 'सेकंद नंतर'); + assert.equal(moment().add({d: 5}).fromNow(), '५ दिवस नंतर', '५ दिवस नंतर'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'आज रात्री २:०० वाजता', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'आज रात्री २:२५ वाजता', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 3}).calendar(), 'आज सकाळी ५:०० वाजता', 'Now plus 3 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'उद्या रात्री २:०० वाजता', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'आज रात्री १:०० वाजता', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'काल रात्री २:०० वाजता', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd[,] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd[,] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd[,] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[मागील] dddd[,] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[मागील] dddd[,] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[मागील] dddd[,] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('meridiem', function (assert) { + assert.equal(moment([2011, 2, 23, 2, 30]).format('a'), 'रात्री', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('a'), 'सकाळी', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('a'), 'दुपारी', 'during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('a'), 'सायंकाळी', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('a'), 'सायंकाळी', 'late evening'); + assert.equal(moment([2011, 2, 23, 21, 20]).format('a'), 'रात्री', 'night'); + + assert.equal(moment([2011, 2, 23, 2, 30]).format('A'), 'रात्री', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('A'), 'सकाळी', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('A'), 'दुपारी', ' during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('A'), 'सायंकाळी', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('A'), 'सायंकाळी', 'late evening'); + assert.equal(moment([2011, 2, 23, 21, 20]).format('A'), 'रात्री', 'night'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '१ ०१ १', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '१ ०१ १', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '२ ०२ २', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '२ ०२ २', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '३ ०३ ३', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('meridiem invariant', function (assert) { + var h, m, t1, t2; + for (h = 0; h < 24; ++h) { + for (m = 0; m < 60; m += 15) { + t1 = moment.utc([2000, 0, 1, h, m]); + t2 = moment(t1.format('A h:mm'), 'A h:mm'); + assert.equal(t2.format('HH:mm'), t1.format('HH:mm'), + 'meridiem at ' + t1.format('HH:mm')); + } + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ms-my'); + + test('parse', function (assert) { + 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) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15.25.50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + }); + + test('format month', function (assert) { + 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++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'beberapa saat', '44 saat = beberapa saat'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'seminit', '45 saat = seminit'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'seminit', '89 saat = seminit'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minit', '90 saat = 2 minit'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minit', '44 minit = 44 minit'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'sejam', '45 minit = sejam'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'sejam', '89 minit = sejam'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 jam', '90 minit = 2 jam'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 jam', '5 jam = 5 jam'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 jam', '21 jam = 21 jam'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'sehari', '22 jam = sehari'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'sehari', '35 jam = sehari'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 hari', '36 jam = 2 hari'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'sehari', '1 hari = sehari'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 hari', '5 hari = 5 hari'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 hari', '25 hari = 25 hari'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'sebulan', '26 hari = sebulan'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'sebulan', '30 hari = sebulan'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'sebulan', '45 hari = sebulan'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 bulan', '46 hari = 2 bulan'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 bulan', '75 hari = 2 bulan'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 bulan', '76 hari = 3 bulan'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'sebulan', '1 bulan = sebulan'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 bulan', '5 bulan = 5 bulan'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'setahun', '345 hari = setahun'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 tahun', '548 hari = 2 tahun'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'setahun', '1 tahun = setahun'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 tahun', '5 tahun = 5 tahun'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'dalam beberapa saat', 'prefix'); + assert.equal(moment(0).from(30000), 'beberapa saat yang lepas', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'beberapa saat yang lepas', 'waktu sekarang dari sekarang sepatutnya menunjukkan sebagai telah lepas'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'dalam beberapa saat', 'dalam beberapa saat'); + assert.equal(moment().add({d: 5}).fromNow(), 'dalam 5 hari', 'dalam 5 hari'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Hari ini pukul 02.00', 'hari ini pada waktu yang sama'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Hari ini pukul 02.25', 'Sekarang tambah 25 minit'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Hari ini pukul 03.00', 'Sekarang tambah 1 jam'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Esok pukul 02.00', 'esok pada waktu yang sama'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Hari ini pukul 01.00', 'Sekarang tolak 1 jam'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Kelmarin pukul 02.00', 'kelmarin pada waktu yang sama'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [pukul] LT'), 'Hari ini + ' + i + ' hari waktu sekarang'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [pukul] LT'), 'Hari ini + ' + i + ' hari permulaan hari'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [pukul] LT'), 'Hari ini + ' + i + ' hari tamat hari'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [lepas] [pukul] LT'), 'Hari ini - ' + i + ' hari waktu sekarang'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [lepas] [pukul] LT'), 'Hari ini - ' + i + ' hari permulaan hari'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [lepas] [pukul] LT'), 'Hari ini - ' + i + ' hari tamat hari'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 minggu lepas'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'dalam 1 minggu'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 minggu lepas'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'dalam 2 minggu'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 sepatutnya minggu 1'); + assert.equal(moment([2012, 0, 7]).week(), 2, 'Jan 7 2012 sepatutnya minggu 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 sepatutnya minggu 2'); + assert.equal(moment([2012, 0, 14]).week(), 3, 'Jan 14 2012 sepatutnya minggu 3'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 sepatutnya minggu 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 53, 'Dec 31 2006 sepatutnya minggu 53'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 sepatutnya minggu 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 sepatutnya minggu 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 sepatutnya minggu 1'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 sepatutnya minggu 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 sepatutnya minggu 2'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 30]).week(), 52, 'Dec 30 2007 sepatutnya minggu 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 sepatutnya minggu 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 sepatutnya minggu 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 sepatutnya minggu 1'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 sepatutnya minggu 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 sepatutnya minggu 2'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 52, 'Dec 29 2002 sepatutnya minggu 52'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 sepatutnya minggu 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 sepatutnya minggu 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 sepatutnya minggu 1'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 sepatutnya minggu 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 sepatutnya minggu 2'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 52, 'Dec 28 2008 sepatutnya minggu 52'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 sepatutnya minggu 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 sepatutnya minggu 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 sepatutnya minggu 1'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 sepatutnya minggu 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 sepatutnya minggu 2'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 52, 'Dec 27 2009 sepatutnya minggu 52'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 sepatutnya minggu 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 sepatutnya minggu 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 sepatutnya minggu 1'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 sepatutnya minggu 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 sepatutnya minggu 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 52, 'Dec 26 2010 sepatutnya minggu 52'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 sepatutnya minggu 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 sepatutnya minggu 1'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 sepatutnya minggu 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 sepatutnya minggu 2'); + }); + + test('weeks year starting sunday format', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', 'Jan 1 2012 sepatutnya minggu 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '2 02 2', 'Jan 7 2012 sepatutnya minggu 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', 'Jan 8 2012 sepatutnya minggu 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '3 03 3', 'Jan 14 2012 sepatutnya minggu 3'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3', 'Jan 15 2012 sepatutnya minggu 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('meridiem invariant', function (assert) { + var h, m, t1, t2; + for (h = 0; h < 24; ++h) { + for (m = 0; m < 60; m += 15) { + t1 = moment.utc([2000, 0, 1, h, m]); + t2 = moment(t1.format('A h:mm'), 'A h:mm'); + assert.equal(t2.format('HH:mm'), t1.format('HH:mm'), + 'meridiem at ' + t1.format('HH:mm')); + } + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('my'); + + test('parse', function (assert) { + var tests = 'ဇန်နဝါရီ ဇန်_ဖေဖော်ဝါရီ ဖေ_မတ် မတ်_ဧပြီ ပြီ_မေ မေ_ဇွန် ဇွန်_ဇူလိုင် လိုင်_သြဂုတ် သြ_စက်တင်ဘာ စက်_အောက်တိုဘာ အောက်_နိုဝင်ဘာ နို_ဒီဇင်ဘာ ဒီ'.split('_'), + i; + + function equalTest (input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'တနင်္ဂနွေ, ဖေဖော်ဝါရီ ၁၄ ၂၀၁၀, ၃:၂၅:၅၀ pm'], + ['ddd, hA', 'နွေ, ၃PM'], + ['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', 'pm PM'], + ['[နှစ်၏] DDDo [ရက်မြောက်]', 'နှစ်၏ ၄၅ ရက်မြောက်'], + ['LTS', '၁၅:၂၅:၅၀'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '၁', '၁'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '၂', '၂'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '၃', '၃'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '၄', '၄'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '၅', '၅'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '၆', '၆'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '၇', '၇'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '၈', '၈'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '၉', '၉'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '၁၀', '၁၀'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '၁၁', '၁၁'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '၁၂', '၁၂'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '၁၃', '၁၃'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '၁၄', '၁၄'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '၁၅', '၁၅'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '၁၆', '၁၆'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '၁၇', '၁၇'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '၁၈', '၁၈'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '၁၉', '၁၉'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '၂၀', '၂၀'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '၂၁', '၂၁'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '၂၂', '၂၂'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '၂၃', '၂၃'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '၂၄', '၂၄'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '၂၅', '၂၅'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '၂၆', '၂၆'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '၂၇', '၂၇'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '၂၈', '၂၈'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '၂၉', '၂၉'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '၃၀', '၃၀'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '၃၁', '၃၁'); + }); + + test('format month', function (assert) { + var expected = 'ဇန်နဝါရီ ဇန်_ဖေဖော်ဝါရီ ဖေ_မတ် မတ်_ဧပြီ ပြီ_မေ မေ_ဇွန် ဇွန်_ဇူလိုင် လိုင်_သြဂုတ် သြ_စက်တင်ဘာ စက်_အောက်တိုဘာ အောက်_နိုဝင်ဘာ နို_ဒီဇင်ဘာ ဒီ'.split('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'တနင်္ဂနွေ နွေ နွေ_တနင်္လာ လာ လာ_အင်္ဂါ ဂါ ဂါ_ဗုဒ္ဓဟူး ဟူး ဟူး_ကြာသပတေး ကြာ ကြာ_သောကြာ သော သော_စနေ နေ နေ'.split('_'), + i; + + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({ + s: 44 + }), true), 'စက္ကန်.အနည်းငယ်', '၄၄ စက္ကန်. = စက္ကန်.အနည်းငယ်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + s: 45 + }), true), 'တစ်မိနစ်', '၄၅ စက္ကန်. = တစ်မိနစ်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + s: 89 + }), true), 'တစ်မိနစ်', '၈၉ စက္ကန်. = တစ်မိနစ်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + s: 90 + }), true), '၂ မိနစ်', '၉၀ စက္ကန်. = ၂ မိနစ်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + m: 44 + }), true), '၄၄ မိနစ်', '၄၄ မိနစ် = ၄၄ မိနစ်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + m: 45 + }), true), 'တစ်နာရီ', '၄၅ မိနစ် = ၁ နာရီ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + m: 89 + }), true), 'တစ်နာရီ', '၈၉ မိနစ် = တစ်နာရီ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + m: 90 + }), true), '၂ နာရီ', 'မိနစ် ၉၀= ၂ နာရီ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + h: 5 + }), true), '၅ နာရီ', '၅ နာရီ= ၅ နာရီ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + h: 21 + }), true), '၂၁ နာရီ', '၂၁ နာရီ =၂၁ နာရီ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + h: 22 + }), true), 'တစ်ရက်', '၂၂ နာရီ =တစ်ရက်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + h: 35 + }), true), 'တစ်ရက်', '၃၅ နာရီ =တစ်ရက်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + h: 36 + }), true), '၂ ရက်', '၃၆ နာရီ = ၂ ရက်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 1 + }), true), 'တစ်ရက်', '၁ ရက်= တစ်ရက်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 5 + }), true), '၅ ရက်', '၅ ရက် = ၅ ရက်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 25 + }), true), '၂၅ ရက်', '၂၅ ရက်= ၂၅ ရက်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 26 + }), true), 'တစ်လ', '၂၆ ရက် = တစ်လ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 30 + }), true), 'တစ်လ', 'ရက် ၃၀ = တစ်လ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 43 + }), true), 'တစ်လ', '၄၃ ရက် = တစ်လ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 46 + }), true), '၂ လ', '၄၆ ရက် = ၂ လ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 74 + }), true), '၂ လ', '၇၅ ရက်= ၂ လ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 76 + }), true), '၃ လ', '၇၆ ရက် = ၃ လ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + M: 1 + }), true), 'တစ်လ', '၁ လ = တစ်လ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + M: 5 + }), true), '၅ လ', '၅ လ = ၅ လ'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 345 + }), true), 'တစ်နှစ်', '၃၄၅ ရက် = တစ်နှစ်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + d: 548 + }), true), '၂ နှစ်', '၅၄၈ ရက် = ၂ နှစ်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + y: 1 + }), true), 'တစ်နှစ်', '၁ နှစ် = တစ်နှစ်'); + assert.equal(start.from(moment([2007, 1, 28]).add({ + y: 5 + }), true), '၅ နှစ်', '၅ နှစ် = ၅ နှစ်'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'လာမည့် စက္ကန်.အနည်းငယ် မှာ', 'prefix'); + assert.equal(moment(0).from(30000), 'လွန်ခဲ့သော စက္ကန်.အနည်းငယ် က', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'လွန်ခဲ့သော စက္ကန်.အနည်းငယ် က', 'ယခုမှစပြီး အတိတ်တွင်ဖော်ပြသလိုဖော်ပြမည်'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({ + s: 30 + }).fromNow(), 'လာမည့် စက္ကန်.အနည်းငယ် မှာ', 'လာမည့် စက္ကန်.အနည်းငယ် မှာ'); + assert.equal(moment().add({ + d: 5 + }).fromNow(), 'လာမည့် ၅ ရက် မှာ', 'လာမည့် ၅ ရက် မှာ'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'ယနေ. ၀၂:၀၀ မှာ', 'ယနေ. ဒီအချိန်'); + assert.equal(moment(a).add({ + m: 25 + }).calendar(), 'ယနေ. ၀၂:၂၅ မှာ', 'ယခုမှ ၂၅ မိနစ်ပေါင်းထည့်'); + assert.equal(moment(a).add({ + h: 1 + }).calendar(), 'ယနေ. ၀၃:၀၀ မှာ', 'ယခုမှ ၁ နာရီပေါင်းထည့်'); + assert.equal(moment(a).add({ + d: 1 + }).calendar(), 'မနက်ဖြန် ၀၂:၀၀ မှာ', 'မနက်ဖြန် ဒီအချိန်'); + assert.equal(moment(a).subtract({ + h: 1 + }).calendar(), 'ယနေ. ၀၁:၀၀ မှာ', 'ယခုမှ ၁ နာရီနှုတ်'); + assert.equal(moment(a).subtract({ + d: 1 + }).calendar(), 'မနေ.က ၀၂:၀၀ မှာ', 'မနေ.က ဒီအချိန်'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({ + d: i + }); + assert.equal(m.calendar(), m.format('dddd LT [မှာ]'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd LT [မှာ]'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd LT [မှာ]'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({ + d: i + }); + assert.equal(m.calendar(), m.format('[ပြီးခဲ့သော] dddd LT [မှာ]'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[ပြီးခဲ့သော] dddd LT [မှာ]'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[ပြီးခဲ့သော] dddd LT [မှာ]'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({ + w: 1 + }), + weeksFromNow = moment().add({ + w: 1 + }); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), 'လွန်ခဲ့သော ၁ ပတ်က'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), '၁ ပတ်အတွင်း'); + + weeksAgo = moment().subtract({ + w: 2 + }); + weeksFromNow = moment().add({ + w: 2 + }); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '၂ ပတ် အရင်က'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), '၂ ပတ် အတွင်း'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '၅၂ ၅၂ ၅၂', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '၁ ၀၁ ၁', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '၁ ၀၁ ၁', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '၂ ၀၂ ၂', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '၂ ၀၂ ၂', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('nb'); + + test('parse', function (assert) { + 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('_'), + i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['[den] DDDo [dagen i året]', 'den 45. dagen i året'], + ['LTS', '15.25.50'], + ['L', '14.02.2010'], + ['LL', '14. februar 2010'], + ['LLL', '14. februar 2010 kl. 15.25'], + ['LLLL', 'søndag 14. februar 2010 kl. 15.25'], + ['l', '14.2.2010'], + ['ll', '14. feb 2010'], + ['lll', '14. feb 2010 kl. 15.25'], + ['llll', 'søn 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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'søndag søn sø_mandag man ma_tirsdag tirs ti_onsdag ons on_torsdag tors to_fredag fre fr_lørdag lør lø'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'noen sekunder', '44 sekunder = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'ett minutt', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'ett minutt', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutter', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutter', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'en time', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'en time', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 timer', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 timer', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 timer', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'en dag', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'en dag', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dager', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'en dag', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dager', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dager', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'en måned', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'en måned', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'en måned', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 måneder', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 måneder', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 måneder', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'en måned', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 måneder', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ett år', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 år', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ett år', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 år', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'om noen sekunder', 'prefix'); + assert.equal(moment(0).from(30000), 'for noen sekunder siden', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'for noen sekunder siden', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'om noen sekunder', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'om 5 dager', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'i dag kl. 2.00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'i dag kl. 2.25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'i dag kl. 3.00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'i morgen kl. 2.00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'i dag kl. 1.00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'i går kl. 2.00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [kl.] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [kl.] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [kl.] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[forrige] dddd [kl.] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[forrige] dddd [kl.] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[forrige] dddd [kl.] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ne'); + + test('parse', function (assert) { + var tests = 'जनवरी जन._फेब्रुवरी फेब्रु._मार्च मार्च_अप्रिल अप्रि._मई मई_जुन जुन_जुलाई जुलाई._अगष्ट अग._सेप्टेम्बर सेप्ट._अक्टोबर अक्टो._नोभेम्बर नोभे._डिसेम्बर डिसे.'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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', 'बेलुका बेलुका'], + ['LTS', 'बेलुकाको ३:२५:५० बजे'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '१', '१'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '२', '२'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '३', '३'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '४', '४'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '५', '५'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '६', '६'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '७', '७'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '८', '८'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '९', '९'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '१०', '१०'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '११', '११'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '१२', '१२'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '१३', '१३'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '१४', '१४'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '१५', '१५'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '१६', '१६'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '१७', '१७'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '१८', '१८'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '१९', '१९'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '२०', '२०'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '२१', '२१'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '२२', '२२'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '२३', '२३'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '२४', '२४'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '२५', '२५'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '२६', '२६'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '२७', '२७'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '२८', '२८'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '२९', '२९'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '३०', '३०'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '३१', '३१'); + }); + + test('format month', function (assert) { + var expected = 'जनवरी जन._फेब्रुवरी फेब्रु._मार्च मार्च_अप्रिल अप्रि._मई मई_जुन जुन_जुलाई जुलाई._अगष्ट अग._सेप्टेम्बर सेप्ट._अक्टोबर अक्टो._नोभेम्बर नोभे._डिसेम्बर डिसे.'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'आइतबार आइत. आइ._सोमबार सोम. सो._मङ्गलबार मङ्गल. मङ्_बुधबार बुध. बु._बिहिबार बिहि. बि._शुक्रबार शुक्र. शु._शनिबार शनि. श.'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'केही समय', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'एक मिनेट', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'एक मिनेट', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '२ मिनेट', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '४४ मिनेट', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'एक घण्टा', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'एक घण्टा', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '२ घण्टा', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '५ घण्टा', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '२१ घण्टा', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'एक दिन', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'एक दिन', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '२ दिन', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'एक दिन', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '५ दिन', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '२५ दिन', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'एक महिना', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'एक महिना', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'एक महिना', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '२ महिना', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '२ महिना', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '३ महिना', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'एक महिना', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '५ महिना', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'एक बर्ष', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '२ बर्ष', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'एक बर्ष', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '५ बर्ष', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'केही समयमा', 'prefix'); + assert.equal(moment(0).from(30000), 'केही समय अगाडी', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'केही समय अगाडी', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'केही समयमा', 'केही समयमा'); + assert.equal(moment().add({d: 5}).fromNow(), '५ दिनमा', '५ दिनमा'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'आज रातीको २:०० बजे', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'आज रातीको २:२५ बजे', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'आज बिहानको ३:०० बजे', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'भोली रातीको २:०० बजे', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'आज रातीको १:०० बजे', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'हिजो रातीको २:०० बजे', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('[आउँदो] dddd[,] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[आउँदो] dddd[,] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[आउँदो] dddd[,] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[गएको] dddd[,] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[गएको] dddd[,] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[गएको] dddd[,] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('meridiem', function (assert) { + assert.equal(moment([2011, 2, 23, 2, 30]).format('a'), 'राती', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('a'), 'बिहान', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('a'), 'दिउँसो', 'during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('a'), 'बेलुका', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('a'), 'साँझ', 'late evening'); + assert.equal(moment([2011, 2, 23, 21, 20]).format('a'), 'राती', 'night'); + + assert.equal(moment([2011, 2, 23, 2, 30]).format('A'), 'राती', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('A'), 'बिहान', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('A'), 'दिउँसो', 'during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('A'), 'बेलुका', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('A'), 'साँझ', 'late evening'); + assert.equal(moment([2011, 2, 23, 21, 20]).format('A'), 'राती', 'night'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '१ ०१ १', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '१ ०१ १', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '२ ०२ २', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '२ ०२ २', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '३ ०३ ३', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('meridiem invariant', function (assert) { + var h, m, t1, t2; + for (h = 0; h < 24; ++h) { + for (m = 0; m < 60; m += 15) { + t1 = moment.utc([2000, 0, 1, h, m]); + t2 = moment(t1.format('A h:mm'), 'A h:mm'); + assert.equal(t2.format('HH:mm'), t1.format('HH:mm'), + 'meridiem at ' + t1.format('HH:mm')); + } + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('nl'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1ste', '1ste'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2de', '2de'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3de', '3de'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4de', '4de'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5de', '5de'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6de', '6de'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7de', '7de'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8ste', '8ste'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9de', '9de'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10de', '10de'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11de', '11de'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12de', '12de'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13de', '13de'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14de', '14de'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15de', '15de'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16de', '16de'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17de', '17de'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18de', '18de'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19de', '19de'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20ste', '20ste'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21ste', '21ste'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22ste', '22ste'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23ste', '23ste'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24ste', '24ste'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25ste', '25ste'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26ste', '26ste'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27ste', '27ste'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28ste', '28ste'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29ste', '29ste'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30ste', '30ste'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31ste', '31ste'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'zondag zo. Zo_maandag ma. Ma_dinsdag di. Di_woensdag wo. Wo_donderdag do. Do_vrijdag vr. Vr_zaterdag za. Za'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'een paar seconden', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'één minuut', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'één minuut', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuten', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuten', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'één uur', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'één uur', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 uur', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 uur', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 uur', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'één dag', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'één dag', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dagen', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'één dag', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dagen', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dagen', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'één maand', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'één maand', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'één maand', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 maanden', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 maanden', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 maanden', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'één maand', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 maanden', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'één jaar', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 jaar', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'één jaar', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 jaar', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'over een paar seconden', 'prefix'); + assert.equal(moment(0).from(30000), 'een paar seconden geleden', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'een paar seconden geleden', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'over een paar seconden', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'over 5 dagen', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'vandaag om 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'vandaag om 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'vandaag om 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'morgen om 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'vandaag om 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'gisteren om 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [om] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [om] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [om] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[afgelopen] dddd [om] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[afgelopen] dddd [om] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[afgelopen] dddd [om] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('month abbreviation', function (assert) { + assert.equal(moment([2012, 5, 23]).format('D-MMM-YYYY'), '23-jun-2012', 'format month abbreviation surrounded by dashes should not include a dot'); + assert.equal(moment([2012, 5, 23]).format('D MMM YYYY'), '23 jun. 2012', 'format month abbreviation not surrounded by dashes should include a dot'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52ste', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1ste', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1ste', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2de', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2de', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('nn'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['L', '14.02.2010'], + ['LL', '14 februar 2010'], + ['LLL', '14 februar 2010 15:25'], + ['LLLL', 'sundag 14 februar 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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'nokre sekund', '44 sekunder = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'eit minutt', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'eit minutt', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutt', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutt', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ein time', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ein time', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 timar', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 timar', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 timar', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'ein dag', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'ein dag', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dagar', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'ein dag', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dagar', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dagar', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ein månad', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ein månad', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ein månad', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 månader', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 månader', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 månader', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ein månad', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 månader', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'eit år', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 år', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'eit år', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 år', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'om nokre sekund', 'prefix'); + assert.equal(moment(0).from(30000), 'for nokre sekund sidan', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'for nokre sekund sidan', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'om nokre sekund', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'om 5 dagar', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'I dag klokka 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'I dag klokka 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'I dag klokka 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'I morgon klokka 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'I dag klokka 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'I går klokka 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [klokka] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [klokka] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [klokka] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[Føregåande] dddd [klokka] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[Føregåande] dddd [klokka] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[Føregåande] dddd [klokka] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('pl'); + + test('parse', function (assert) { + var tests = 'styczeń stycznia sty_luty lutego lut_marzec marca mar_kwiecień kwietnia kwi_maj maja maj_czerwiec czerwca cze_lipiec lipca lip_sierpień sierpnia sie_wrzesień września wrz_październik października paź_listopad listopada lis_grudzień grudnia gru'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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][2], 'MMM', i); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][2], 'MMMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][2].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][2].toLocaleUpperCase(), 'MMMM', i); + } + }); + + test('parse strict', function (assert) { + var tests = 'styczeń stycznia sty_luty lutego lut_marzec marca mar_kwiecień kwietnia kwi_maj maja maj_czerwiec czerwca cze_lipiec lipca lip_sierpień sierpnia sie_wrzesień września wrz_październik października paź_listopad listopada lis_grudzień grudnia gru'.split('_'), i; + function equalTest(input, mmm, i) { + assert.equal(moment(input, mmm, true).month(), i, input + ' should be month ' + (i + 1)); + } + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(' '); + equalTest(tests[i][0], 'MMMM', i); + equalTest(tests[i][1], 'MMMM', i); + equalTest(tests[i][2], 'MMM', i); + equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i); + equalTest(tests[i][2].toLocaleLowerCase(), 'MMM', i); + equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i); + equalTest(tests[i][2].toLocaleUpperCase(), 'MMM', i); + } + }); + + test('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'kilka sekund', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'minuta', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'minuta', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuty', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuty', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'godzina', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'godzina', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 godziny', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 godzin', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 godzin', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), '1 dzień', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), '1 dzień', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dni', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), '1 dzień', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dni', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dni', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'miesiąc', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'miesiąc', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'miesiąc', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 miesiące', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 miesiące', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 miesiące', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'miesiąc', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 miesięcy', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'rok', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 lata', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'rok', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 lat', '5 years = 5 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 112}), true), '112 lat', '112 years = 112 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 122}), true), '122 lata', '122 years = 122 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 213}), true), '213 lat', '213 years = 213 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 223}), true), '223 lata', '223 years = 223 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'za kilka sekund', 'prefix'); + assert.equal(moment(0).from(30000), 'kilka sekund temu', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'kilka sekund temu', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'za kilka sekund', 'in a few seconds'); + assert.equal(moment().add({h: 1}).fromNow(), 'za godzinę', 'in an hour'); + assert.equal(moment().add({d: 5}).fromNow(), 'za 5 dni', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Dziś o 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Dziś o 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Dziś o 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Jutro o 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Dziś o 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Wczoraj o 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('[W] dddd [o] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[W] dddd [o] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[W] dddd [o] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + 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}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days current time'); + + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days beginning of day'); + + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('pt-br'); + + test('parse', function (assert) { + 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('_'), i; + + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['L', '14/02/2010'], + ['LL', '14 de Fevereiro de 2010'], + ['LLL', '14 de Fevereiro de 2010 às 15:25'], + ['LLLL', 'Domingo, 14 de Fevereiro de 2010 às 15:25'], + ['l', '14/2/2010'], + ['ll', '14 de Fev de 2010'], + ['lll', '14 de Fev de 2010 às 15:25'], + ['llll', 'Dom, 14 de Fev de 2010 às 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'segundos', '44 seconds = seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'um minuto', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'um minuto', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutos', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutos', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'uma hora', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'uma hora', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 horas', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 horas', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 horas', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'um dia', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'um dia', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dias', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'um dia', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dias', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dias', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'um mês', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'um mês', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'um mês', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 meses', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 meses', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 meses', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'um mês', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 meses', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'um ano', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 anos', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'um ano', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 anos', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'em segundos', 'prefix'); + assert.equal(moment(0).from(30000), 'segundos atrás', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'em segundos', 'in seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'em 5 dias', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Hoje às 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Hoje às 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Hoje às 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Amanhã às 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Hoje às 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Ontem às 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [às] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [às] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [às] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.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); + assert.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); + assert.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('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday format', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1º', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1º', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2º', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2º', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3º', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('pt'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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', '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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'segundos', '44 seconds = seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'um minuto', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'um minuto', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minutos', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minutos', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'uma hora', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'uma hora', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 horas', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 horas', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 horas', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'um dia', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'um dia', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dias', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'um dia', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dias', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dias', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'um mês', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'um mês', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'um mês', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 meses', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 meses', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 meses', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'um mês', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 meses', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'um ano', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 anos', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'um ano', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 anos', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'em segundos', 'prefix'); + assert.equal(moment(0).from(30000), 'há segundos', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'em segundos', 'in seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'em 5 dias', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Hoje às 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Hoje às 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Hoje às 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Amanhã às 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Hoje às 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Ontem às 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [às] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [às] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [às] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.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); + assert.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); + assert.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('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52º', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1º', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1º', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2º', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2º', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ro'); + + test('parse', function (assert) { + var tests = 'ianuarie ian._februarie febr._martie mart._aprilie apr._mai mai_iunie iun._iulie iul._august aug._septembrie sept._octombrie oct._noiembrie nov._decembrie dec.'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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 febr.'], + ['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'], + ['LTS', '15:25:50'], + ['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 febr. 2010'], + ['lll', '14 febr. 2010 15:25'], + ['llll', 'Dum, 14 febr. 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + }); + + test('format month', function (assert) { + var expected = 'ianuarie ian._februarie febr._martie mart._aprilie apr._mai mai_iunie iun._iulie iul._august aug._septembrie sept._octombrie oct._noiembrie nov._decembrie dec.'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'câteva secunde', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'un minut', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'un minut', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minute', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 de minute', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'o oră', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'o oră', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 ore', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 ore', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 de ore', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'o zi', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'o zi', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 zile', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'o zi', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 zile', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 de zile', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'o lună', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'o lună', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'o lună', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 luni', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 luni', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 luni', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'o lună', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 luni', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'un an', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 ani', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'un an', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 ani', '5 years = 5 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 19}), true), '19 ani', '19 years = 19 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 20}), true), '20 de ani', '20 years = 20 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 100}), true), '100 de ani', '100 years = 100 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 101}), true), '101 ani', '101 years = 101 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 119}), true), '119 ani', '119 years = 119 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 120}), true), '120 de ani', '120 years = 120 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 219}), true), '219 ani', '219 years = 219 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 220}), true), '220 de ani', '220 years = 220 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'peste câteva secunde', 'prefix'); + assert.equal(moment(0).from(30000), 'câteva secunde în urmă', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'câteva secunde în urmă', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'peste câteva secunde', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'peste 5 zile', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'azi la 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'azi la 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'azi la 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'mâine la 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'azi la 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'ieri la 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [la] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [la] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [la] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[fosta] dddd [la] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[fosta] dddd [la] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[fosta] dddd [la] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ru'); + + test('parse', function (assert) { + var tests = 'январь янв_февраль фев_март март_апрель апр_май май_июнь июнь_июль июль_август авг_сентябрь сен_октябрь окт_ноябрь ноя_декабрь дек'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('parse exceptional case', function (assert) { + assert.equal(moment('11 мая 1989', ['DD MMMM YYYY']).format('DD-MM-YYYY'), '11-05-1989'); + }); + + test('format', function (assert) { + var a = [ + ['dddd, Do MMMM YYYY, HH:mm:ss', 'воскресенье, 14-го февраля 2010, 15: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', '7 7-я 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'дня дня'], + ['DDDo [день года]', '45-й день года'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format meridiem', function (assert) { + assert.equal(moment([2012, 11, 28, 0, 0]).format('A'), 'ночи', 'night'); + assert.equal(moment([2012, 11, 28, 3, 59]).format('A'), 'ночи', 'night'); + assert.equal(moment([2012, 11, 28, 4, 0]).format('A'), 'утра', 'morning'); + assert.equal(moment([2012, 11, 28, 11, 59]).format('A'), 'утра', 'morning'); + assert.equal(moment([2012, 11, 28, 12, 0]).format('A'), 'дня', 'afternoon'); + assert.equal(moment([2012, 11, 28, 16, 59]).format('A'), 'дня', 'afternoon'); + assert.equal(moment([2012, 11, 28, 17, 0]).format('A'), 'вечера', 'evening'); + assert.equal(moment([2012, 11, 28, 23, 59]).format('A'), 'вечера', 'evening'); + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1-й', '1-й'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2-й', '2-й'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3-й', '3-й'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4-й', '4-й'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5-й', '5-й'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6-й', '6-й'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7-й', '7-й'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8-й', '8-й'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9-й', '9-й'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10-й', '10-й'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11-й', '11-й'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12-й', '12-й'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13-й', '13-й'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14-й', '14-й'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15-й', '15-й'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16-й', '16-й'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17-й', '17-й'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18-й', '18-й'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19-й', '19-й'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20-й', '20-й'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21-й', '21-й'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22-й', '22-й'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23-й', '23-й'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24-й', '24-й'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25-й', '25-й'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26-й', '26-й'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27-й', '27-й'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28-й', '28-й'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29-й', '29-й'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30-й', '30-й'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31-й', '31-й'); + }); + + test('format month', function (assert) { + var expected = 'январь янв_февраль фев_март март_апрель апр_май май_июнь июнь_июль июль_август авг_сентябрь сен_октябрь окт_ноябрь ноя_декабрь дек'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format month case', function (assert) { + var months = { + 'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + 'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_') + }, i; + for (i = 0; i < 12; i++) { + assert.equal(moment([2011, i, 1]).format('D MMMM'), '1 ' + months.accusative[i], '1 ' + months.accusative[i]); + assert.equal(moment([2011, i, 1]).format('MMMM'), months.nominative[i], '1 ' + months.nominative[i]); + } + }); + + test('format month short case', function (assert) { + var monthsShort = { + 'nominative': 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'), + 'accusative': 'янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек'.split('_') + }, i; + for (i = 0; i < 12; i++) { + assert.equal(moment([2011, i, 1]).format('D MMM'), '1 ' + monthsShort.accusative[i], '1 ' + monthsShort.accusative[i]); + assert.equal(moment([2011, i, 1]).format('MMM'), monthsShort.nominative[i], '1 ' + monthsShort.nominative[i]); + } + }); + + test('format month case with escaped symbols', function (assert) { + var months = { + 'nominative': 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + 'accusative': 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_') + }, i; + for (i = 0; i < 12; i++) { + assert.equal(moment([2013, i, 1]).format('D[] MMMM'), '1 ' + months.accusative[i], '1 ' + months.accusative[i]); + assert.equal(moment([2013, i, 1]).format('[<i>]D[</i>] [<b>]MMMM[</b>]'), '<i>1</i> <b>' + months.accusative[i] + '</b>', '1 <b>' + months.accusative[i] + '</b>'); + assert.equal(moment([2013, i, 1]).format('D[-й день] MMMM'), '1-й день ' + months.accusative[i], '1-й день ' + months.accusative[i]); + assert.equal(moment([2013, i, 1]).format('D, MMMM'), '1, ' + months.nominative[i], '1, ' + months.nominative[i]); + } + }); + + test('format month short case with escaped symbols', function (assert) { + var monthsShort = { + 'nominative': 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'), + 'accusative': 'янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек'.split('_') + }, i; + for (i = 0; i < 12; i++) { + assert.equal(moment([2013, i, 1]).format('D[] MMM'), '1 ' + monthsShort.accusative[i], '1 ' + monthsShort.accusative[i]); + assert.equal(moment([2013, i, 1]).format('[<i>]D[</i>] [<b>]MMM[</b>]'), '<i>1</i> <b>' + monthsShort.accusative[i] + '</b>', '1 <b>' + monthsShort.accusative[i] + '</b>'); + assert.equal(moment([2013, i, 1]).format('D[-й день] MMM'), '1-й день ' + monthsShort.accusative[i], '1-й день ' + monthsShort.accusative[i]); + assert.equal(moment([2013, i, 1]).format('D, MMM'), '1, ' + monthsShort.nominative[i], '1, ' + monthsShort.nominative[i]); + } + }); + + test('format week', function (assert) { + var expected = 'воскресенье вс вс_понедельник пн пн_вторник вт вт_среда ср ср_четверг чт чт_пятница пт пт_суббота сб сб'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'несколько секунд', '44 seconds = seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'минута', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'минута', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 минуты', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 31}), true), '31 минута', '31 minutes = 31 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 минуты', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'час', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'час', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 часа', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 часов', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 час', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'день', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'день', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 дня', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'день', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 дней', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 11}), true), '11 дней', '11 days = 11 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 21}), true), '21 день', '21 days = 21 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 дней', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'месяц', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'месяц', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'месяц', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 месяца', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 месяца', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 месяца', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'месяц', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 месяцев', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'год', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 года', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'год', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 лет', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'через несколько секунд', 'prefix'); + assert.equal(moment(0).from(30000), 'несколько секунд назад', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'через несколько секунд', 'in seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'через 5 дней', 'in 5 days'); + assert.equal(moment().add({m: 31}).fromNow(), 'через 31 минуту', 'in 31 minutes = in 31 minutes'); + assert.equal(moment().subtract({m: 31}).fromNow(), '31 минуту назад', '31 minutes ago = 31 minutes ago'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Сегодня в 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Сегодня в 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Сегодня в 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Завтра в 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Сегодня в 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Вчера в 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + function makeFormat(d) { + return d.day() === 2 ? '[Во] dddd [в] LT' : '[В] dddd [в] LT'; + } + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m, now; + + function makeFormatLast(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'; + } + } + + function makeFormatThis(d) { + switch (d.day()) { + case 2: + return '[Во] dddd [в] LT'; + case 0: + case 1: + case 3: + case 4: + case 5: + case 6: + return '[В] dddd [в] LT'; + } + } + + now = moment().startOf('week'); + for (i = 2; i < 7; i++) { + m = moment(now).subtract({d: i}); + assert.equal(m.calendar(now), m.format(makeFormatLast(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(now), m.format(makeFormatLast(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(now), m.format(makeFormatLast(m)), 'Today - ' + i + ' days end of day'); + } + + now = moment().endOf('week'); + for (i = 2; i < 7; i++) { + m = moment(now).subtract({d: i}); + assert.equal(m.calendar(now), m.format(makeFormatThis(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(now), m.format(makeFormatThis(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(now), m.format(makeFormatThis(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-я', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-я', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2-я', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2-я', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3-я', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('si'); + + /*jshint -W100*/ + test('parse', function (assert) { + var tests = 'ජනවාරි ජන_පෙබරවාරි පෙබ_මාර්තු මාර්_අප්රේල් අප්_මැයි මැයි_ජූනි ජූනි_ජූලි ජූලි_අගෝස්තු අගෝ_සැප්තැම්බර් සැප්_ඔක්තෝබර් ඔක්_නොවැම්බර් නොවැ_දෙසැම්බර් දෙසැ'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['YYYY MMMM Do dddd, a h:mm:ss', '2010 පෙබරවාරි 14 වැනි ඉරිදා, ප.ව. 3:25:50'], + ['YYYY MMMM Do dddd, a h:mm:ss', '2010 පෙබරවාරි 14 වැනි ඉරිදා, ප.ව. 3:25:50'], + ['ddd, A h', 'ඉරි, පස් වරු 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'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'ප.ව. පස් වරු'], + ['[වසරේ] DDDo [දිනය]', 'වසරේ 45 වැනි දිනය'], + ['LTS', 'ප.ව. 3:25:50'], + ['LT', 'ප.ව. 3:25'], + ['L', '2010/02/14'], + ['LL', '2010 පෙබරවාරි 14'], + ['LLL', '2010 පෙබරවාරි 14, ප.ව. 3:25'], + ['LLLL', '2010 පෙබරවාරි 14 වැනි ඉරිදා, ප.ව. 3:25:50'], + ['l', '2010/2/14'], + ['ll', '2010 පෙබ 14'], + ['lll', '2010 පෙබ 14, ප.ව. 3:25'], + ['llll', '2010 පෙබ 14 වැනි ඉරි, ප.ව. 3:25:50'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1 වැනි', '1 වැනි'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2 වැනි', '2 වැනි'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3 වැනි', '3 වැනි'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4 වැනි', '4 වැනි'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5 වැනි', '5 වැනි'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6 වැනි', '6 වැනි'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7 වැනි', '7 වැනි'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8 වැනි', '8 වැනි'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9 වැනි', '9 වැනි'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10 වැනි', '10 වැනි'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11 වැනි', '11 වැනි'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12 වැනි', '12 වැනි'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13 වැනි', '13 වැනි'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14 වැනි', '14 වැනි'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15 වැනි', '15 වැනි'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16 වැනි', '16 වැනි'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17 වැනි', '17 වැනි'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18 වැනි', '18 වැනි'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19 වැනි', '19 වැනි'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20 වැනි', '20 වැනි'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21 වැනි', '21 වැනි'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22 වැනි', '22 වැනි'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23 වැනි', '23 වැනි'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24 වැනි', '24 වැනි'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25 වැනි', '25 වැනි'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26 වැනි', '26 වැනි'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27 වැනි', '27 වැනි'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28 වැනි', '28 වැනි'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29 වැනි', '29 වැනි'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30 වැනි', '30 වැනි'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31 වැනි', '31 වැනි'); + }); + + test('format month', function (assert) { + var expected = 'ජනවාරි ජන_පෙබරවාරි පෙබ_මාර්තු මාර්_අප්රේල් අප්_මැයි මැයි_ජූනි ජූනි_ජූලි ජූලි_අගෝස්තු අගෝ_සැප්තැම්බර් සැප්_ඔක්තෝබර් ඔක්_නොවැම්බර් නොවැ_දෙසැම්බර් දෙසැ'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'ඉරිදා ඉරි ඉ_සඳුදා සඳු ස_අඟහරුවාදා අඟ අ_බදාදා බදා බ_බ්රහස්පතින්දා බ්රහ බ්ර_සිකුරාදා සිකු සි_සෙනසුරාදා සෙන සෙ'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'තත්පර කිහිපය', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'මිනිත්තුව', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'මිනිත්තුව', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), 'මිනිත්තු 2', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), 'මිනිත්තු 44', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'පැය', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'පැය', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), 'පැය 2', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), 'පැය 5', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), 'පැය 21', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'දිනය', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'දිනය', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), 'දින 2', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'දිනය', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), 'දින 5', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), 'දින 25', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'මාසය', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'මාසය', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'මාසය', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), 'මාස 2', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), 'මාස 2', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), 'මාස 3', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'මාසය', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), 'මාස 5', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'වසර', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), 'වසර 2', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'වසර', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), 'වසර 5', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'තත්පර කිහිපයකින්', 'prefix'); + assert.equal(moment(0).from(30000), 'තත්පර කිහිපයකට පෙර', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'තත්පර කිහිපයකට පෙර', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'තත්පර කිහිපයකින්', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'දින 5කින්', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'අද පෙ.ව. 2:00ට', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'අද පෙ.ව. 2:25ට', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'අද පෙ.ව. 3:00ට', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'හෙට පෙ.ව. 2:00ට', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'අද පෙ.ව. 1:00ට', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'ඊයේ පෙ.ව. 2:00ට', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd LT[ට]'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd LT[ට]'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd LT[ට]'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[පසුගිය] dddd LT[ට]'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[පසුගිය] dddd LT[ට]'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[පසුගිය] dddd LT[ට]'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('sk'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, monthIndex) { + assert.equal(moment(input, mmm).month(), monthIndex, input + ' should be month ' + (monthIndex + 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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'pár sekúnd', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'minúta', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'minúta', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minúty', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minút', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'hodina', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'hodina', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 hodiny', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 hodín', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 hodín', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'deň', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'deň', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dni', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'deň', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dní', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dní', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'mesiac', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'mesiac', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'mesiac', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 mesiace', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 mesiace', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mesiace', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'mesiac', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mesiacov', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'rok', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 roky', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'rok', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 rokov', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'za pár sekúnd', 'prefix'); + assert.equal(moment(0).from(30000), 'pred pár sekundami', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'pred pár sekundami', 'now from now should display as in the past'); + }); + + test('fromNow (future)', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'za pár sekúnd', 'in a few seconds'); + assert.equal(moment().add({m: 1}).fromNow(), 'za minútu', 'in a minute'); + assert.equal(moment().add({m: 3}).fromNow(), 'za 3 minúty', 'in 3 minutes'); + assert.equal(moment().add({m: 10}).fromNow(), 'za 10 minút', 'in 10 minutes'); + assert.equal(moment().add({h: 1}).fromNow(), 'za hodinu', 'in an hour'); + assert.equal(moment().add({h: 3}).fromNow(), 'za 3 hodiny', 'in 3 hours'); + assert.equal(moment().add({h: 10}).fromNow(), 'za 10 hodín', 'in 10 hours'); + assert.equal(moment().add({d: 1}).fromNow(), 'za deň', 'in a day'); + assert.equal(moment().add({d: 3}).fromNow(), 'za 3 dni', 'in 3 days'); + assert.equal(moment().add({d: 10}).fromNow(), 'za 10 dní', 'in 10 days'); + assert.equal(moment().add({M: 1}).fromNow(), 'za mesiac', 'in a month'); + assert.equal(moment().add({M: 3}).fromNow(), 'za 3 mesiace', 'in 3 months'); + assert.equal(moment().add({M: 10}).fromNow(), 'za 10 mesiacov', 'in 10 months'); + assert.equal(moment().add({y: 1}).fromNow(), 'za rok', 'in a year'); + assert.equal(moment().add({y: 3}).fromNow(), 'za 3 roky', 'in 3 years'); + assert.equal(moment().add({y: 10}).fromNow(), 'za 10 rokov', 'in 10 years'); + }); + + test('fromNow (past)', function (assert) { + assert.equal(moment().subtract({s: 30}).fromNow(), 'pred pár sekundami', 'a few seconds ago'); + assert.equal(moment().subtract({m: 1}).fromNow(), 'pred minútou', 'a minute ago'); + assert.equal(moment().subtract({m: 3}).fromNow(), 'pred 3 minútami', '3 minutes ago'); + assert.equal(moment().subtract({m: 10}).fromNow(), 'pred 10 minútami', '10 minutes ago'); + assert.equal(moment().subtract({h: 1}).fromNow(), 'pred hodinou', 'an hour ago'); + assert.equal(moment().subtract({h: 3}).fromNow(), 'pred 3 hodinami', '3 hours ago'); + assert.equal(moment().subtract({h: 10}).fromNow(), 'pred 10 hodinami', '10 hours ago'); + assert.equal(moment().subtract({d: 1}).fromNow(), 'pred dňom', 'a day ago'); + assert.equal(moment().subtract({d: 3}).fromNow(), 'pred 3 dňami', '3 days ago'); + assert.equal(moment().subtract({d: 10}).fromNow(), 'pred 10 dňami', '10 days ago'); + assert.equal(moment().subtract({M: 1}).fromNow(), 'pred mesiacom', 'a month ago'); + assert.equal(moment().subtract({M: 3}).fromNow(), 'pred 3 mesiacmi', '3 months ago'); + assert.equal(moment().subtract({M: 10}).fromNow(), 'pred 10 mesiacmi', '10 months ago'); + assert.equal(moment().subtract({y: 1}).fromNow(), 'pred rokom', 'a year ago'); + assert.equal(moment().subtract({y: 3}).fromNow(), 'pred 3 rokmi', '3 years ago'); + assert.equal(moment().subtract({y: 10}).fromNow(), 'pred 10 rokmi', '10 years ago'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'dnes o 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'dnes o 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'dnes o 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'zajtra o 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'dnes o 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'včera o 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m, nextDay; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + 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; + } + assert.equal(m.calendar(), m.format('[' + nextDay + '] [o] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[' + nextDay + '] [o] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[' + nextDay + '] [o] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m, lastDay; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + 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; + } + assert.equal(m.calendar(), m.format('[' + lastDay + '] [o] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[' + lastDay + '] [o] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[' + lastDay + '] [o] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('humanize duration', function (assert) { + assert.equal(moment.duration(1, 'minutes').humanize(), 'minúta', 'a minute (future)'); + assert.equal(moment.duration(1, 'minutes').humanize(true), 'za minútu', 'in a minute'); + assert.equal(moment.duration(-1, 'minutes').humanize(), 'minúta', 'a minute (past)'); + assert.equal(moment.duration(-1, 'minutes').humanize(true), 'pred minútou', 'a minute ago'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('sl'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'nedelja ned. ne_ponedeljek pon. po_torek tor. to_sreda sre. sr_četrtek čet. če_petek pet. pe_sobota sob. so'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'nekaj sekund', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'ena minuta', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'ena minuta', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuti', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minut', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ena ura', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ena ura', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 uri', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 ur', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 ur', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'en dan', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'en dan', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dni', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'en dan', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dni', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dni', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'en mesec', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'en mesec', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'en mesec', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 meseca', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 meseca', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 mesece', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'en mesec', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mesecev', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'eno leto', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 leti', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'eno leto', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 let', '5 years = 5 years'); + + assert.equal(start.from(moment([2007, 1, 28]).add({m: 1}), true), 'ena minuta', 'a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 2}), true), '2 minuti', '2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 3}), true), '3 minute', '3 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 4}), true), '4 minute', '4 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 5}), true), '5 minut', '5 minutes'); + + assert.equal(start.from(moment([2007, 1, 28]).add({h: 1}), true), 'ena ura', 'an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 2}), true), '2 uri', '2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 3}), true), '3 ure', '3 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 4}), true), '4 ure', '4 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 ur', '5 hours'); + + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'en dan', 'a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 2}), true), '2 dni', '2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 3}), true), '3 dni', '3 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 4}), true), '4 dni', '4 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dni', '5 days'); + + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'en mesec', 'a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 2}), true), '2 meseca', '2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 3}), true), '3 mesece', '3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 4}), true), '4 mesece', '4 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 mesecev', '5 months'); + + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'eno leto', 'a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 2}), true), '2 leti', '2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 3}), true), '3 leta', '3 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 4}), true), '4 leta', '4 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 let', '5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'čez nekaj sekund', 'prefix'); + assert.equal(moment(0).from(30000), 'pred nekaj sekundami', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'pred nekaj sekundami', 'now from now should display as in the past'); + }); + + test('fromNow (future)', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'čez nekaj sekund', 'in a few seconds'); + assert.equal(moment().add({m: 1}).fromNow(), 'čez eno minuto', 'in a minute'); + assert.equal(moment().add({m: 2}).fromNow(), 'čez 2 minuti', 'in 2 minutes'); + assert.equal(moment().add({m: 3}).fromNow(), 'čez 3 minute', 'in 3 minutes'); + assert.equal(moment().add({m: 4}).fromNow(), 'čez 4 minute', 'in 4 minutes'); + assert.equal(moment().add({m: 5}).fromNow(), 'čez 5 minut', 'in 5 minutes'); + + assert.equal(moment().add({h: 1}).fromNow(), 'čez eno uro', 'in an hour'); + assert.equal(moment().add({h: 2}).fromNow(), 'čez 2 uri', 'in 2 hours'); + assert.equal(moment().add({h: 3}).fromNow(), 'čez 3 ure', 'in 3 hours'); + assert.equal(moment().add({h: 4}).fromNow(), 'čez 4 ure', 'in 4 hours'); + assert.equal(moment().add({h: 5}).fromNow(), 'čez 5 ur', 'in 5 hours'); + + assert.equal(moment().add({d: 1}).fromNow(), 'čez en dan', 'in a day'); + assert.equal(moment().add({d: 2}).fromNow(), 'čez 2 dni', 'in 2 days'); + assert.equal(moment().add({d: 3}).fromNow(), 'čez 3 dni', 'in 3 days'); + assert.equal(moment().add({d: 4}).fromNow(), 'čez 4 dni', 'in 4 days'); + assert.equal(moment().add({d: 5}).fromNow(), 'čez 5 dni', 'in 5 days'); + + assert.equal(moment().add({M: 1}).fromNow(), 'čez en mesec', 'in a month'); + assert.equal(moment().add({M: 2}).fromNow(), 'čez 2 meseca', 'in 2 months'); + assert.equal(moment().add({M: 3}).fromNow(), 'čez 3 mesece', 'in 3 months'); + assert.equal(moment().add({M: 4}).fromNow(), 'čez 4 mesece', 'in 4 months'); + assert.equal(moment().add({M: 5}).fromNow(), 'čez 5 mesecev', 'in 5 months'); + + assert.equal(moment().add({y: 1}).fromNow(), 'čez eno leto', 'in a year'); + assert.equal(moment().add({y: 2}).fromNow(), 'čez 2 leti', 'in 2 years'); + assert.equal(moment().add({y: 3}).fromNow(), 'čez 3 leta', 'in 3 years'); + assert.equal(moment().add({y: 4}).fromNow(), 'čez 4 leta', 'in 4 years'); + assert.equal(moment().add({y: 5}).fromNow(), 'čez 5 let', 'in 5 years'); + + assert.equal(moment().subtract({s: 30}).fromNow(), 'pred nekaj sekundami', 'a few seconds ago'); + + assert.equal(moment().subtract({m: 1}).fromNow(), 'pred eno minuto', 'a minute ago'); + assert.equal(moment().subtract({m: 2}).fromNow(), 'pred 2 minutama', '2 minutes ago'); + assert.equal(moment().subtract({m: 3}).fromNow(), 'pred 3 minutami', '3 minutes ago'); + assert.equal(moment().subtract({m: 4}).fromNow(), 'pred 4 minutami', '4 minutes ago'); + assert.equal(moment().subtract({m: 5}).fromNow(), 'pred 5 minutami', '5 minutes ago'); + + assert.equal(moment().subtract({h: 1}).fromNow(), 'pred eno uro', 'an hour ago'); + assert.equal(moment().subtract({h: 2}).fromNow(), 'pred 2 urama', '2 hours ago'); + assert.equal(moment().subtract({h: 3}).fromNow(), 'pred 3 urami', '3 hours ago'); + assert.equal(moment().subtract({h: 4}).fromNow(), 'pred 4 urami', '4 hours ago'); + assert.equal(moment().subtract({h: 5}).fromNow(), 'pred 5 urami', '5 hours ago'); + + assert.equal(moment().subtract({d: 1}).fromNow(), 'pred enim dnem', 'a day ago'); + assert.equal(moment().subtract({d: 2}).fromNow(), 'pred 2 dnevoma', '2 days ago'); + assert.equal(moment().subtract({d: 3}).fromNow(), 'pred 3 dnevi', '3 days ago'); + assert.equal(moment().subtract({d: 4}).fromNow(), 'pred 4 dnevi', '4 days ago'); + assert.equal(moment().subtract({d: 5}).fromNow(), 'pred 5 dnevi', '5 days ago'); + + assert.equal(moment().subtract({M: 1}).fromNow(), 'pred enim mesecem', 'a month ago'); + assert.equal(moment().subtract({M: 2}).fromNow(), 'pred 2 mesecema', '2 months ago'); + assert.equal(moment().subtract({M: 3}).fromNow(), 'pred 3 meseci', '3 months ago'); + assert.equal(moment().subtract({M: 4}).fromNow(), 'pred 4 meseci', '4 months ago'); + assert.equal(moment().subtract({M: 5}).fromNow(), 'pred 5 meseci', '5 months ago'); + + assert.equal(moment().subtract({y: 1}).fromNow(), 'pred enim letom', 'a year ago'); + assert.equal(moment().subtract({y: 2}).fromNow(), 'pred 2 letoma', '2 years ago'); + assert.equal(moment().subtract({y: 3}).fromNow(), 'pred 3 leti', '3 years ago'); + assert.equal(moment().subtract({y: 4}).fromNow(), 'pred 4 leti', '4 years ago'); + assert.equal(moment().subtract({y: 5}).fromNow(), 'pred 5 leti', '5 years ago'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'danes ob 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'danes ob 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'danes ob 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'jutri ob 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'danes ob 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'včeraj ob 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, 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}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + return '[prejšnjo] [nedeljo] [ob] LT'; + case 3: + return '[prejšnjo] [sredo] [ob] LT'; + case 6: + return '[prejšnjo] [soboto] [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}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1.', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1.', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2.', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2.', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3.', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('sq'); + + test('parse', function (assert) { + 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) { + assert.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('format', function (assert) { + 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', 'MD MD'], + ['[the] DDDo [day of the year]', 'the 45. day of the year'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('meridiem', function (assert) { + assert.equal(moment([2011, 2, 23, 0, 0]).format('A'), 'PD', 'before dawn'); + assert.equal(moment([2011, 2, 23, 12, 0]).format('A'), 'MD', 'noon'); + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + 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++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var i, + expected = 'E Diel Die D_E Hënë Hën H_E Martë Mar Ma_E Mërkurë Mër Më_E Enjte Enj E_E Premte Pre P_E Shtunë Sht Sh'.split('_'); + + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'disa sekonda', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'një minutë', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'një minutë', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuta', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuta', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'një orë', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'një orë', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 orë', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 orë', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 orë', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'një ditë', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'një ditë', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 ditë', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'një ditë', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 ditë', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 ditë', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'një muaj', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'një muaj', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'një muaj', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 muaj', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 muaj', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 muaj', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'një muaj', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 muaj', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'një vit', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 vite', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'një vit', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 vite', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'në disa sekonda', 'prefix'); + assert.equal(moment(0).from(30000), 'disa sekonda më parë', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'disa sekonda më parë', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'në disa sekonda', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'në 5 ditë', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Sot në 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Sot në 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Sot në 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Nesër në 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Sot në 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Dje në 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [në] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [në] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [në] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [e kaluar në] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.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); + assert.equal(m.calendar(), m.format('dddd [e kaluar në] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52.', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1.', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1.', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2.', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2.', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('sr-cyrl'); + + test('parse', function (assert) { + var tests = 'јануар јан._фебруар феб._март мар._април апр._мај мај_јун јун_јул јул_август авг._септембар сеп._октобар окт._новембар нов._децембар дец.'.split('_'), + i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, Do MMMM 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + var expected = 'јануар јан._фебруар феб._март мар._април апр._мај мај_јун јун_јул јул_август авг._септембар сеп._октобар окт._новембар нов._децембар дец.'.split('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'недеља нед. не_понедељак пон. по_уторак уто. ут_среда сре. ср_четвртак чет. че_петак пет. пе_субота суб. су'.split('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'неколико секунди', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'један минут', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'један минут', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 минуте', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 минута', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'један сат', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'један сат', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 сата', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 сати', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 сати', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'дан', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'дан', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 дана', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'дан', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 дана', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 дана', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'месец', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'месец', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'месец', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 месеца', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 месеца', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 месеца', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'месец', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 месеци', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'годину', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 године', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'годину', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 година', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'за неколико секунди', 'prefix'); + assert.equal(moment(0).from(30000), 'пре неколико секунди', 'prefix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'пре неколико секунди', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'за неколико секунди', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'за 5 дана', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'данас у 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'данас у 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'данас у 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'сутра у 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'данас у 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'јуче у 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + return '[у] [недељу] [у] LT'; + case 3: + return '[у] [среду] [у] LT'; + case 6: + return '[у] [суботу] [у] LT'; + case 1: + case 2: + case 4: + case 5: + return '[у] dddd [у] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + function makeFormat(d) { + var lastWeekDay = [ + '[прошле] [недеље] [у] LT', + '[прошлог] [понедељка] [у] LT', + '[прошлог] [уторка] [у] LT', + '[прошле] [среде] [у] LT', + '[прошлог] [четвртка] [у] LT', + '[прошлог] [петка] [у] LT', + '[прошле] [суботе] [у] LT' + ]; + + return lastWeekDay[d.day()]; + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1.', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1.', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2.', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2.', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3.', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('sr'); + + test('parse', function (assert) { + var tests = 'januar jan._februar feb._mart mar._april apr._maj maj_jun jun_jul jul_avgust avg._septembar sep._oktobar okt._novembar nov._decembar dec.'.split('_'), + i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.'); + }); + + test('format month', function (assert) { + var expected = 'januar jan._februar feb._mart mar._april apr._maj maj_jun jun_jul jul_avgust avg._septembar sep._oktobar okt._novembar nov._decembar dec.'.split('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'nedelja ned. ne_ponedeljak pon. po_utorak uto. ut_sreda sre. sr_četvrtak čet. če_petak pet. pe_subota sub. su'.split('_'), + i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'nekoliko sekundi', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'jedan minut', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'jedan minut', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minute', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuta', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'jedan sat', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'jedan sat', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 sata', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 sati', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 sati', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'dan', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'dan', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dana', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'dan', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dana', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dana', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'mesec', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'mesec', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'mesec', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 meseca', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 meseca', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 meseca', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'mesec', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 meseci', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'godinu', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 godine', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'godinu', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 godina', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'za nekoliko sekundi', 'prefix'); + assert.equal(moment(0).from(30000), 'pre nekoliko sekundi', 'prefix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'pre nekoliko sekundi', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'za nekoliko sekundi', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'za 5 dana', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'danas u 2:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'danas u 2:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'danas u 3:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'sutra u 2:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'danas u 1:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'juče u 2:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + function makeFormat(d) { + switch (d.day()) { + case 0: + return '[u] [nedelju] [u] LT'; + case 3: + return '[u] [sredu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + } + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + function makeFormat(d) { + var lastWeekDay = [ + '[prošle] [nedelje] [u] LT', + '[prošlog] [ponedeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + + return lastWeekDay[d.day()]; + } + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1.', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1.', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2.', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2.', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3.', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('sv'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1a', '1a'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2a', '2a'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3e', '3e'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4e', '4e'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5e', '5e'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6e', '6e'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7e', '7e'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8e', '8e'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9e', '9e'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10e', '10e'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11e', '11e'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12e', '12e'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13e', '13e'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14e', '14e'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15e', '15e'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16e', '16e'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17e', '17e'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18e', '18e'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19e', '19e'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20e', '20e'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21a', '21a'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22a', '22a'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23e', '23e'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24e', '24e'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25e', '25e'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26e', '26e'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27e', '27e'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28e', '28e'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29e', '29e'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30e', '30e'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31a', '31a'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'några sekunder', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'en minut', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'en minut', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuter', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuter', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'en timme', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'en timme', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 timmar', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 timmar', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 timmar', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'en dag', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'en dag', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 dagar', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'en dag', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 dagar', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 dagar', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'en månad', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'en månad', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'en månad', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 månader', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 månader', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 månader', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'en månad', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 månader', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ett år', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 år', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ett år', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 år', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'om några sekunder', 'prefix'); + assert.equal(moment(0).from(30000), 'för några sekunder sedan', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'för några sekunder sedan', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'om några sekunder', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'om 5 dagar', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Idag 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Idag 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Idag 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Imorgon 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Idag 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Igår 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('[På] dddd LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[På] dddd LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[På] dddd LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[I] dddd[s] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[I] dddd[s] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[I] dddd[s] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52a', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1a', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1a', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2a', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2a', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('ta'); + + test('parse', function (assert) { + var tests = 'ஜனவரி ஜனவரி_பிப்ரவரி பிப்ரவரி_மார்ச் மார்ச்_ஏப்ரல் ஏப்ரல்_மே மே_ஜூன் ஜூன்_ஜூலை ஜூலை_ஆகஸ்ட் ஆகஸ்ட்_செப்டெம்பர் செப்டெம்பர்_அக்டோபர் அக்டோபர்_நவம்பர் நவம்பர்_டிசம்பர் டிசம்பர்'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'ஞாயிற்றுக்கிழமை, பிப்ரவரி 14வது 2010, 3:25:50 எற்பாடு'], + ['ddd, hA', 'ஞாயிறு, 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', ' எற்பாடு எற்பாடு'], + ['[ஆண்டின்] DDDo [நாள்]', 'ஆண்டின் 45வது நாள்'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1வது', '1வது'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2வது', '2வது'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3வது', '3வது'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4வது', '4வது'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5வது', '5வது'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6வது', '6வது'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7வது', '7வது'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8வது', '8வது'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9வது', '9வது'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10வது', '10வது'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11வது', '11வது'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12வது', '12வது'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13வது', '13வது'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14வது', '14வது'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15வது', '15வது'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16வது', '16வது'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17வது', '17வது'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18வது', '18வது'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19வது', '19வது'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20வது', '20வது'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21வது', '21வது'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22வது', '22வது'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23வது', '23வது'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24வது', '24வது'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25வது', '25வது'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26வது', '26வது'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27வது', '27வது'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28வது', '28வது'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29வது', '29வது'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30வது', '30வது'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31வது', '31வது'); + }); + + test('format month', function (assert) { + var expected = 'ஜனவரி ஜனவரி_பிப்ரவரி பிப்ரவரி_மார்ச் மார்ச்_ஏப்ரல் ஏப்ரல்_மே மே_ஜூன் ஜூன்_ஜூலை ஜூலை_ஆகஸ்ட் ஆகஸ்ட்_செப்டெம்பர் செப்டெம்பர்_அக்டோபர் அக்டோபர்_நவம்பர் நவம்பர்_டிசம்பர் டிசம்பர்'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'ஞாயிற்றுக்கிழமை ஞாயிறு ஞா_திங்கட்கிழமை திங்கள் தி_செவ்வாய்கிழமை செவ்வாய் செ_புதன்கிழமை புதன் பு_வியாழக்கிழமை வியாழன் வி_வெள்ளிக்கிழமை வெள்ளி வெ_சனிக்கிழமை சனி ச'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'ஒரு சில விநாடிகள்', '44 விநாடிகள் = ஒரு சில விநாடிகள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'ஒரு நிமிடம்', '45 விநாடிகள் = ஒரு நிமிடம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'ஒரு நிமிடம்', '89 விநாடிகள் = ஒரு நிமிடம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 நிமிடங்கள்', '90 விநாடிகள் = 2 நிமிடங்கள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 நிமிடங்கள்', '44 நிமிடங்கள் = 44 நிமிடங்கள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ஒரு மணி நேரம்', '45 நிமிடங்கள் = ஒரு மணி நேரம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ஒரு மணி நேரம்', '89 நிமிடங்கள் = ஒரு மணி நேரம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 மணி நேரம்', '90 நிமிடங்கள் = 2 மணி நேரம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 மணி நேரம்', '5 மணி நேரம் = 5 மணி நேரம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 மணி நேரம்', '21 மணி நேரம் = 21 மணி நேரம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'ஒரு நாள்', '22 மணி நேரம் = ஒரு நாள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'ஒரு நாள்', '35 மணி நேரம் = ஒரு நாள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 நாட்கள்', '36 மணி நேரம் = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'ஒரு நாள்', '1 நாள் = ஒரு நாள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 நாட்கள்', '5 நாட்கள் = 5 நாட்கள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 நாட்கள்', '25 நாட்கள் = 25 நாட்கள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ஒரு மாதம்', '26 நாட்கள் = ஒரு மாதம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ஒரு மாதம்', '30 நாட்கள் = ஒரு மாதம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ஒரு மாதம்', '45 நாட்கள் = ஒரு மாதம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 மாதங்கள்', '46 நாட்கள் = 2 மாதங்கள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 மாதங்கள்', '75 நாட்கள் = 2 மாதங்கள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 மாதங்கள்', '76 நாட்கள் = 3 மாதங்கள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ஒரு மாதம்', '1 மாதம் = ஒரு மாதம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 மாதங்கள்', '5 மாதங்கள் = 5 மாதங்கள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ஒரு வருடம்', '345 நாட்கள் = ஒரு வருடம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 ஆண்டுகள்', '548 நாட்கள் = 2 ஆண்டுகள்'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ஒரு வருடம்', '1 வருடம் = ஒரு வருடம்'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 ஆண்டுகள்', '5 ஆண்டுகள் = 5 ஆண்டுகள்'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'ஒரு சில விநாடிகள் இல்', 'prefix'); + assert.equal(moment(0).from(30000), 'ஒரு சில விநாடிகள் முன்', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'ஒரு சில விநாடிகள் முன்', 'இப்போது இருந்து கடந்த காலத்தில் காட்ட வேண்டும்'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'ஒரு சில விநாடிகள் இல்', 'ஒரு சில விநாடிகள் இல்'); + assert.equal(moment().add({d: 5}).fromNow(), '5 நாட்கள் இல்', '5 நாட்கள் இல்'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'இன்று 02:00', 'இன்று 02:00'); + assert.equal(moment(a).add({m: 25}).calendar(), 'இன்று 02:25', 'இன்று 02:25'); + assert.equal(moment(a).add({h: 1}).calendar(), 'இன்று 03:00', 'இன்று 03:00'); + assert.equal(moment(a).add({d: 1}).calendar(), 'நாளை 02:00', 'நாளை 02:00'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'இன்று 01:00', 'இன்று 01:00'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'நேற்று 02:00', 'நேற்று 02:00'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd, LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd, LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd, LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[கடந்த வாரம்] dddd, LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[கடந்த வாரம்] dddd, LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[கடந்த வாரம்] dddd, LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('meridiem', function (assert) { + assert.equal(moment([2011, 2, 23, 0, 30]).format('a'), ' யாமம்', '(after) midnight'); + assert.equal(moment([2011, 2, 23, 2, 30]).format('a'), ' வைகறை', 'before dawn'); + assert.equal(moment([2011, 2, 23, 9, 30]).format('a'), ' காலை', 'morning'); + assert.equal(moment([2011, 2, 23, 14, 30]).format('a'), ' எற்பாடு', 'during day'); + assert.equal(moment([2011, 2, 23, 17, 30]).format('a'), ' எற்பாடு', 'evening'); + assert.equal(moment([2011, 2, 23, 19, 30]).format('a'), ' மாலை', 'late evening'); + assert.equal(moment([2011, 2, 23, 23, 30]).format('a'), ' யாமம்', '(before) midnight'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('meridiem invariant', function (assert) { + var h, m, t1, t2; + for (h = 0; h < 24; ++h) { + for (m = 0; m < 60; m += 15) { + t1 = moment.utc([2000, 0, 1, h, m]); + t2 = moment(t1.format('A h:mm'), 'A h:mm'); + assert.equal(t2.format('HH:mm'), t1.format('HH:mm'), + 'meridiem at ' + t1.format('HH:mm')); + } + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('th'); + + test('parse', function (assert) { + var tests = 'มกราคม มกรา_กุมภาพันธ์ กุมภา_มีนาคม มีนา_เมษายน เมษา_พฤษภาคม พฤษภา_มิถุนายน มิถุนา_กรกฎาคม กรกฎา_สิงหาคม สิงหา_กันยายน กันยา_ตุลาคม ตุลา_พฤศจิกายน พฤศจิกา_ธันวาคม ธันวา'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15 นาฬิกา 25 นาที 50 วินาที'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format month', function (assert) { + var expected = 'มกราคม มกรา_กุมภาพันธ์ กุมภา_มีนาคม มีนา_เมษายน เมษา_พฤษภาคม พฤษภา_มิถุนายน มิถุนา_กรกฎาคม กรกฎา_สิงหาคม สิงหา_กันยายน กันยา_ตุลาคม ตุลา_พฤศจิกายน พฤศจิกา_ธันวาคม ธันวา'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'อาทิตย์ อาทิตย์ อา._จันทร์ จันทร์ จ._อังคาร อังคาร อ._พุธ พุธ พ._พฤหัสบดี พฤหัส พฤ._ศุกร์ ศุกร์ ศ._เสาร์ เสาร์ ส.'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'ไม่กี่วินาที', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), '1 นาที', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), '1 นาที', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 นาที', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 นาที', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), '1 ชั่วโมง', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), '1 ชั่วโมง', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 ชั่วโมง', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 ชั่วโมง', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 ชั่วโมง', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), '1 วัน', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), '1 วัน', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 วัน', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), '1 วัน', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 วัน', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 วัน', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), '1 เดือน', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), '1 เดือน', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), '1 เดือน', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 เดือน', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 เดือน', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 เดือน', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), '1 เดือน', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 เดือน', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), '1 ปี', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 ปี', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), '1 ปี', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 ปี', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'อีก ไม่กี่วินาที', 'prefix'); + assert.equal(moment(0).from(30000), 'ไม่กี่วินาทีที่แล้ว', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'ไม่กี่วินาทีที่แล้ว', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'อีก ไม่กี่วินาที', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'อีก 5 วัน', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'วันนี้ เวลา 2 นาฬิกา 0 นาที', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'วันนี้ เวลา 2 นาฬิกา 25 นาที', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'วันนี้ เวลา 3 นาฬิกา 0 นาที', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'พรุ่งนี้ เวลา 2 นาฬิกา 0 นาที', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'วันนี้ เวลา 1 นาฬิกา 0 นาที', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'เมื่อวานนี้ เวลา 2 นาฬิกา 0 นาที', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd[หน้า เวลา] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd[หน้า เวลา] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd[หน้า เวลา] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[วัน]dddd[ที่แล้ว เวลา] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[วัน]dddd[ที่แล้ว เวลา] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[วัน]dddd[ที่แล้ว เวลา] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday format', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1', 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2', 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3', 'Jan 15 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('tl-ph'); + + test('parse', function (assert) { + var tests = 'Enero Ene_Pebrero Peb_Marso Mar_Abril Abr_Mayo May_Hunyo Hun_Hulyo Hul_Agosto Ago_Setyembre Set_Oktubre Okt_Nobyembre Nob_Disyembre Dis'.split('_'), + i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'Linggo, Pebrero 14 2010, 3:25:50 pm'], + ['ddd, hA', 'Lin, 3PM'], + ['M Mo MM MMMM MMM', '2 2 02 Pebrero Peb'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 Linggo Lin Li'], + ['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'], + ['LTS', '15:25:50'], + ['L', '02/14/2010'], + ['LL', 'Pebrero 14, 2010'], + ['LLL', 'Pebrero 14, 2010 15:25'], + ['LLLL', 'Linggo, Pebrero 14, 2010 15:25'], + ['l', '2/14/2010'], + ['ll', 'Peb 14, 2010'], + ['lll', 'Peb 14, 2010 15:25'], + ['llll', 'Lin, Peb 14, 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + }); + + test('format month', function (assert) { + var expected = 'Enero Ene_Pebrero Peb_Marso Mar_Abril Abr_Mayo May_Hunyo Hun_Hulyo Hul_Agosto Ago_Setyembre Set_Oktubre Okt_Nobyembre Nob_Disyembre Dis'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Linggo Lin Li_Lunes Lun Lu_Martes Mar Ma_Miyerkules Miy Mi_Huwebes Huw Hu_Biyernes Biy Bi_Sabado Sab Sab'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'ilang segundo', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'isang minuto', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'isang minuto', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuto', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuto', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'isang oras', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'isang oras', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 oras', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 oras', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 oras', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'isang araw', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'isang araw', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 araw', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'isang araw', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 araw', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 araw', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'isang buwan', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'isang buwan', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'isang buwan', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 buwan', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 buwan', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 buwan', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'isang buwan', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 buwan', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'isang taon', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 taon', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'isang taon', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 taon', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'sa loob ng ilang segundo', 'prefix'); + assert.equal(moment(0).from(30000), 'ilang segundo ang nakalipas', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'sa loob ng ilang segundo', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'sa loob ng 5 araw', 'in 5 days'); + }); + + test('same day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Ngayon sa 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Ngayon sa 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Ngayon sa 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Bukas sa 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Ngayon sa 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Kahapon sa 02:00', 'yesterday at the same time'); + }); + + test('same next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [sa] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [sa] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [sa] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('same last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [huling linggo] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [huling linggo] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [huling linggo] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('same all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('tr'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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ü'], + ['LTS', '15:25:50'], + ['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; + + for (i = 0; i < a.length; i++) { + assert.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]); + assert.equal(DDDoDt.add(DDDo[i][0], 'days').format('DDDo'), DDDo[i][1], DDDo[i][0] + ' ---> ' + DDDo[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1\'inci', '1st'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2\'nci', '2nd'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3\'üncü', '3rd'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4\'üncü', '4th'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5\'inci', '5th'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6\'ncı', '6th'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7\'nci', '7th'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8\'inci', '8th'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9\'uncu', '9th'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10\'uncu', '10th'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11\'inci', '11th'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12\'nci', '12th'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13\'üncü', '13th'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14\'üncü', '14th'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15\'inci', '15th'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16\'ncı', '16th'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17\'nci', '17th'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18\'inci', '18th'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19\'uncu', '19th'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20\'nci', '20th'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21\'inci', '21th'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22\'nci', '22th'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23\'üncü', '23th'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24\'üncü', '24th'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25\'inci', '25th'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26\'ncı', '26th'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27\'nci', '27th'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28\'inci', '28th'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29\'uncu', '29th'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30\'uncu', '30th'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31\'inci', '31st'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'birkaç saniye', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'bir dakika', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'bir dakika', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 dakika', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 dakika', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'bir saat', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'bir saat', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 saat', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 saat', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 saat', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'bir gün', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'bir gün', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 gün', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'bir gün', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 gün', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 gün', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'bir ay', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'bir ay', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'bir ay', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 ay', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 ay', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 ay', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'bir ay', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 ay', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'bir yıl', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 yıl', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'bir yıl', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 yıl', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'birkaç saniye sonra', 'prefix'); + assert.equal(moment(0).from(30000), 'birkaç saniye önce', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'birkaç saniye önce', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'birkaç saniye sonra', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), '5 gün sonra', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'bugün saat 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'bugün saat 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'bugün saat 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'yarın saat 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'bugün saat 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'dün 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('[haftaya] dddd [saat] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[haftaya] dddd [saat] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[haftaya] dddd [saat] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.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); + assert.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); + assert.equal(m.calendar(), m.format('[geçen hafta] dddd [saat] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1\'inci', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1\'inci', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2\'nci', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2\'nci', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3\'üncü', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('tzm-latn'); + + test('parse', function (assert) { + 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('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + }); + + test('format month', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + 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('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'imik', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'minuḍ', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'minuḍ', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 minuḍ', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 minuḍ', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'saɛa', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'saɛa', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 tassaɛin', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 tassaɛin', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 tassaɛin', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'ass', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'ass', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 ossan', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'ass', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 ossan', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 ossan', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ayowr', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ayowr', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ayowr', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 iyyirn', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 iyyirn', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 iyyirn', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ayowr', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 iyyirn', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'asgas', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 isgasn', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'asgas', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 isgasn', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'dadkh s yan imik', 'prefix'); + assert.equal(moment(0).from(30000), 'yan imik', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'yan imik', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'dadkh s yan imik', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'dadkh s yan 5 ossan', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'asdkh g 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'asdkh g 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'asdkh g 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'aska g 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'asdkh g 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'assant g 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [g] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [g] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [g] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [g] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [g] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [g] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 31]).week(), 1, 'Dec 31 2011 should be week 1'); + assert.equal(moment([2012, 0, 6]).week(), 1, 'Jan 6 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 2, 'Jan 7 2012 should be week 2'); + assert.equal(moment([2012, 0, 13]).week(), 2, 'Jan 13 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 3, 'Jan 14 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 30]).week(), 1, 'Dec 30 2006 should be week 1'); + assert.equal(moment([2007, 0, 5]).week(), 1, 'Jan 5 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 2, 'Jan 6 2007 should be week 2'); + assert.equal(moment([2007, 0, 12]).week(), 2, 'Jan 12 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 3, 'Jan 13 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 1, 'Dec 29 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 4]).week(), 1, 'Jan 4 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 2, 'Jan 5 2008 should be week 2'); + assert.equal(moment([2008, 0, 11]).week(), 2, 'Jan 11 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 3, 'Jan 12 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 28]).week(), 1, 'Dec 28 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 3]).week(), 1, 'Jan 3 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 2, 'Jan 4 2003 should be week 2'); + assert.equal(moment([2003, 0, 10]).week(), 2, 'Jan 10 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 3, 'Jan 11 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 27]).week(), 1, 'Dec 27 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 2]).week(), 1, 'Jan 2 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 2, 'Jan 3 2009 should be week 2'); + assert.equal(moment([2009, 0, 9]).week(), 2, 'Jan 9 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 3, 'Jan 10 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 26]).week(), 1, 'Dec 26 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 2, 'Jan 2 2010 should be week 2'); + assert.equal(moment([2010, 0, 8]).week(), 2, 'Jan 8 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 3, 'Jan 9 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 7]).week(), 1, 'Jan 7 2011 should be week 1'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 14]).week(), 2, 'Jan 14 2011 should be week 2'); + assert.equal(moment([2011, 0, 15]).week(), 3, 'Jan 15 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 31]).format('w ww wo'), '1 01 1', 'Dec 31 2011 should be week 1'); + assert.equal(moment([2012, 0, 6]).format('w ww wo'), '1 01 1', 'Jan 6 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '2 02 2', 'Jan 7 2012 should be week 2'); + assert.equal(moment([2012, 0, 13]).format('w ww wo'), '2 02 2', 'Jan 13 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '3 03 3', 'Jan 14 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('tzm'); + + test('parse', function (assert) { + var tests = 'ⵉⵏⵏⴰⵢⵔ ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + }); + + test('format month', function (assert) { + var expected = 'ⵉⵏⵏⴰⵢⵔ ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'ⴰⵙⴰⵎⴰⵙ ⴰⵙⴰⵎⴰⵙ ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ ⴰⵢⵏⴰⵙ ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ ⴰⵙⵉⵏⴰⵙ ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ ⴰⴽⵔⴰⵙ ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ ⴰⴽⵡⴰⵙ ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ ⴰⵙⵉⵎⵡⴰⵙ ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ ⴰⵙⵉⴹⵢⴰⵙ ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'ⵉⵎⵉⴽ', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'ⵎⵉⵏⵓⴺ', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'ⵎⵉⵏⵓⴺ', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 ⵎⵉⵏⵓⴺ', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 ⵎⵉⵏⵓⴺ', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'ⵙⴰⵄⴰ', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'ⵙⴰⵄⴰ', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 ⵜⴰⵙⵙⴰⵄⵉⵏ', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 ⵜⴰⵙⵙⴰⵄⵉⵏ', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 ⵜⴰⵙⵙⴰⵄⵉⵏ', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'ⴰⵙⵙ', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'ⴰⵙⵙ', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 oⵙⵙⴰⵏ', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'ⴰⵙⵙ', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 oⵙⵙⴰⵏ', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 oⵙⵙⴰⵏ', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'ⴰⵢoⵓⵔ', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'ⴰⵢoⵓⵔ', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'ⴰⵢoⵓⵔ', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 ⵉⵢⵢⵉⵔⵏ', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 ⵉⵢⵢⵉⵔⵏ', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 ⵉⵢⵢⵉⵔⵏ', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'ⴰⵢoⵓⵔ', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 ⵉⵢⵢⵉⵔⵏ', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'ⴰⵙⴳⴰⵙ', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 ⵉⵙⴳⴰⵙⵏ', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'ⴰⵙⴳⴰⵙ', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 ⵉⵙⴳⴰⵙⵏ', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ ⵉⵎⵉⴽ', 'prefix'); + assert.equal(moment(0).from(30000), 'ⵢⴰⵏ ⵉⵎⵉⴽ', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'ⵢⴰⵏ ⵉⵎⵉⴽ', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ ⵉⵎⵉⴽ', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ 5 oⵙⵙⴰⵏ', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'ⴰⵙⴷⵅ ⴴ 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'ⴰⵙⴷⵅ ⴴ 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'ⴰⵙⴷⵅ ⴴ 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'ⴰⵙⴽⴰ ⴴ 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'ⴰⵙⴷⵅ ⴴ 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'ⴰⵚⴰⵏⵜ ⴴ 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [ⴴ] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [ⴴ] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [ⴴ] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [ⴴ] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [ⴴ] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [ⴴ] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 31]).week(), 1, 'Dec 31 2011 should be week 1'); + assert.equal(moment([2012, 0, 6]).week(), 1, 'Jan 6 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 2, 'Jan 7 2012 should be week 2'); + assert.equal(moment([2012, 0, 13]).week(), 2, 'Jan 13 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 3, 'Jan 14 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 30]).week(), 1, 'Dec 30 2006 should be week 1'); + assert.equal(moment([2007, 0, 5]).week(), 1, 'Jan 5 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 2, 'Jan 6 2007 should be week 2'); + assert.equal(moment([2007, 0, 12]).week(), 2, 'Jan 12 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 3, 'Jan 13 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 1, 'Dec 29 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 4]).week(), 1, 'Jan 4 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 2, 'Jan 5 2008 should be week 2'); + assert.equal(moment([2008, 0, 11]).week(), 2, 'Jan 11 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 3, 'Jan 12 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 28]).week(), 1, 'Dec 28 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 3]).week(), 1, 'Jan 3 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 2, 'Jan 4 2003 should be week 2'); + assert.equal(moment([2003, 0, 10]).week(), 2, 'Jan 10 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 3, 'Jan 11 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 27]).week(), 1, 'Dec 27 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 2]).week(), 1, 'Jan 2 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 2, 'Jan 3 2009 should be week 2'); + assert.equal(moment([2009, 0, 9]).week(), 2, 'Jan 9 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 3, 'Jan 10 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 26]).week(), 1, 'Dec 26 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 2, 'Jan 2 2010 should be week 2'); + assert.equal(moment([2010, 0, 8]).week(), 2, 'Jan 8 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 3, 'Jan 9 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 7]).week(), 1, 'Jan 7 2011 should be week 1'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 14]).week(), 2, 'Jan 14 2011 should be week 2'); + assert.equal(moment([2011, 0, 15]).week(), 3, 'Jan 15 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 31]).format('w ww wo'), '1 01 1', 'Dec 31 2011 should be week 1'); + assert.equal(moment([2012, 0, 6]).format('w ww wo'), '1 01 1', 'Jan 6 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '2 02 2', 'Jan 7 2012 should be week 2'); + assert.equal(moment([2012, 0, 13]).format('w ww wo'), '2 02 2', 'Jan 13 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '3 03 3', 'Jan 14 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('uk'); + + test('parse', function (assert) { + var tests = 'січень січ_лютий лют_березень бер_квітень квіт_травень трав_червень черв_липень лип_серпень серп_вересень вер_жовтень жовт_листопад лист_грудень груд'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, Do MMMM YYYY, HH:mm:ss', 'неділя, 14-го лютого 2010, 15: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', '7 7-й 07'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', 'дня дня'], + ['DDDo [день року]', '45-й день року'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format meridiem', function (assert) { + assert.equal(moment([2012, 11, 28, 0, 0]).format('A'), 'ночі', 'night'); + assert.equal(moment([2012, 11, 28, 3, 59]).format('A'), 'ночі', 'night'); + assert.equal(moment([2012, 11, 28, 4, 0]).format('A'), 'ранку', 'morning'); + assert.equal(moment([2012, 11, 28, 11, 59]).format('A'), 'ранку', 'morning'); + assert.equal(moment([2012, 11, 28, 12, 0]).format('A'), 'дня', 'afternoon'); + assert.equal(moment([2012, 11, 28, 16, 59]).format('A'), 'дня', 'afternoon'); + assert.equal(moment([2012, 11, 28, 17, 0]).format('A'), 'вечора', 'evening'); + assert.equal(moment([2012, 11, 28, 23, 59]).format('A'), 'вечора', 'evening'); + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1-й', '1-й'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2-й', '2-й'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3-й', '3-й'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4-й', '4-й'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5-й', '5-й'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6-й', '6-й'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7-й', '7-й'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8-й', '8-й'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9-й', '9-й'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10-й', '10-й'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11-й', '11-й'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12-й', '12-й'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13-й', '13-й'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14-й', '14-й'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15-й', '15-й'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16-й', '16-й'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17-й', '17-й'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18-й', '18-й'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19-й', '19-й'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20-й', '20-й'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21-й', '21-й'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22-й', '22-й'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23-й', '23-й'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24-й', '24-й'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25-й', '25-й'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26-й', '26-й'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27-й', '27-й'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28-й', '28-й'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29-й', '29-й'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30-й', '30-й'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31-й', '31-й'); + }); + + test('format month', function (assert) { + var expected = 'січень січ_лютий лют_березень бер_квітень квіт_травень трав_червень черв_липень лип_серпень серп_вересень вер_жовтень жовт_листопад лист_грудень груд'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format month case', function (assert) { + var months = { + 'nominative': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_'), + 'accusative': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_') + }, i; + for (i = 0; i < 12; i++) { + assert.equal(moment([2011, i, 1]).format('D MMMM'), '1 ' + months.accusative[i], '1 ' + months.accusative[i]); + assert.equal(moment([2011, i, 1]).format('MMMM'), months.nominative[i], '1 ' + months.nominative[i]); + } + }); + + test('format week', function (assert) { + var expected = 'неділя нд нд_понеділок пн пн_вівторок вт вт_середа ср ср_четвер чт чт_п’ятниця пт пт_субота сб сб'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'декілька секунд', '44 seconds = seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'хвилина', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'хвилина', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 хвилини', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 хвилини', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'годину', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'годину', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 години', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 годин', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 година', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'день', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'день', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 дні', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'день', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 днів', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 11}), true), '11 днів', '11 days = 11 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 21}), true), '21 день', '21 days = 21 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 днів', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'місяць', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'місяць', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'місяць', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 місяці', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 місяці', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 місяці', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'місяць', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 місяців', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'рік', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 роки', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'рік', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 років', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'за декілька секунд', 'prefix'); + assert.equal(moment(0).from(30000), 'декілька секунд тому', 'suffix'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'за декілька секунд', 'in seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'за 5 днів', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Сьогодні о 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Сьогодні о 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Сьогодні о 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Завтра о 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Сьогодні о 01:00', 'Now minus 1 hour'); + assert.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 + assert.equal(moment(a).add({h: 9}).calendar(), 'Сьогодні об 11:00', 'same day at 11 o\'clock'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('[У] dddd [о' + (m.hours() === 11 ? 'б' : '') + '] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[У] dddd [о] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[У] dddd [о] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, 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}); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format(makeFormat(m)), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2011, 11, 26]).week(), 1, 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 12]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 1'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 2'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 1'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 2'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 3'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2011, 11, 26]).format('w ww wo'), '1 01 1-й', 'Dec 26 2011 should be week 1'); + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1-й', 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2-й', 'Jan 2 2012 should be week 2'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2-й', 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3-й', 'Jan 9 2012 should be week 3'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('uz'); + + test('parse', function (assert) { + var tests = 'январь янв_февраль фев_март мар_апрель апр_май май_июнь июнь_июль июль_август авг_сентябрь сен_октябрь окт_ноябрь ноя_декабрь дек'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + var a = [ + ['dddd, Do-MMMM YYYY, h:mm:ss', 'Якшанба, 14-февраль 2010, 3:25:50'], + ['ddd, h:mm', 'Якш, 3:25'], + ['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-куни'], + ['LTS', '15:25:50'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + }); + + test('format month', function (assert) { + var expected = 'январь янв_февраль фев_март мар_апрель апр_май май_июнь июн_июль июл_август авг_сентябрь сен_октябрь окт_ноябрь ноя_декабрь дек'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = 'Якшанба Якш Як_Душанба Душ Ду_Сешанба Сеш Се_Чоршанба Чор Чо_Пайшанба Пай Па_Жума Жум Жу_Шанба Шан Ша'.split('_'), i; + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'фурсат', '44 секунд = фурсат'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'бир дакика', '45 секунд = бир дакика'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'бир дакика', '89 секунд = бир дакика'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 дакика', '90 секунд = 2 дакика'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 дакика', '44 дакика = 44 дакика'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'бир соат', '45 минут = бир соат'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'бир соат', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 соат', '90 минут = 2 соат'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 соат', '5 соат = 5 соат'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 соат', '21 соат = 21 соат'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'бир кун', '22 соат = бир кун'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'бир кун', '35 соат = бир кун'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 кун', '36 соат = 2 кун'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'бир кун', '1 кун = 1 кун'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 кун', '5 кун = 5 кун'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 кун', '25 кун = 25 кун'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'бир ой', '26 кун = бир ой'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'бир ой', '30 кун = бир ой'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'бир ой', '45 кун = бир ой'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 ой', '46 кун = 2 ой'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 ой', '75 кун = 2 ой'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 ой', '76 кун = 3 ой'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'бир ой', 'бир ой = бир ой'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 ой', '5 ой = 5 ой'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'бир йил', '345 кун = бир йил'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 йил', '548 кун = 2 йил'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'бир йил', '1 йил = бир йил'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 йил', '5 йил = 5 йил'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'Якин фурсат ичида', 'prefix'); + assert.equal(moment(0).from(30000), 'Бир неча фурсат олдин', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'Бир неча фурсат олдин', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'Якин фурсат ичида', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), 'Якин 5 кун ичида', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Бугун соат 02:00 да', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Бугун соат 02:25 да', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Бугун соат 03:00 да', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Эртага 02:00 да', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Бугун соат 01:00 да', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Кеча соат 02:00 да', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [куни соат] LT [да]'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [куни соат] LT [да]'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [куни соат] LT [да]'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[Утган] dddd [куни соат] LT [да]'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[Утган] dddd [куни соат] LT [да]'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[Утган] dddd [куни соат] LT [да]'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 2, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 3, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 1, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 1, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 2, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 2, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 3, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 1, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 1, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 2, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 2, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 3, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '2 02 2', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '3 03 3', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('vi'); + + test('parse', function (assert) { + var i, + tests = 'tháng 1,Th01_tháng 2,Th02_tháng 3,Th03_tháng 4,Th04_tháng 5,Th05_tháng 6,Th06_tháng 7,Th07_tháng 8,Th08_tháng 9,Th09_tháng 10,Th10_tháng 11,Th11_tháng 12,Th12'.split('_'); + + function equalTest(input, mmm, i) { + assert.equal(moment(input, mmm).month(), i, input + ' should be month ' + i); + } + + for (i = 0; i < 12; i++) { + tests[i] = tests[i].split(','); + equalTest(tests[i][0], '[tháng] M', i); + equalTest(tests[i][1], '[Th]M', i); + equalTest(tests[i][0], '[tháng] MM', i); + equalTest(tests[i][1], '[Th]MM', i); + equalTest(tests[i][0].toLocaleLowerCase(), '[THÁNG] M', i); + equalTest(tests[i][1].toLocaleLowerCase(), '[TH]M', i); + equalTest(tests[i][0].toLocaleUpperCase(), '[THÁNG] MM', i); + equalTest(tests[i][1].toLocaleUpperCase(), '[TH]MM', i); + } + }); + + test('format', function (assert) { + var a = [ + ['dddd, MMMM Do YYYY, h:mm:ss a', 'chủ nhật, tháng 2 14 2010, 3:25:50 pm'], + ['ddd, hA', 'CN, 3PM'], + ['M Mo MM MMMM MMM', '2 2 02 tháng 2 Th02'], + ['YYYY YY', '2010 10'], + ['D Do DD', '14 14 14'], + ['d do dddd ddd dd', '0 0 chủ nhật CN CN'], + ['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'], + ['[ngày thứ] DDDo [của năm]', 'ngày thứ 45 của năm'], + ['LTS', '15:25:50'], + ['L', '14/02/2010'], + ['LL', '14 tháng 2 năm 2010'], + ['LLL', '14 tháng 2 năm 2010 15:25'], + ['LLLL', 'chủ nhật, 14 tháng 2 năm 2010 15:25'], + ['l', '14/2/2010'], + ['ll', '14 Th02 2010'], + ['lll', '14 Th02 2010 15:25'], + ['llll', 'CN, 14 Th02 2010 15:25'] + ], + b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)), + i; + + for (i = 0; i < a.length; i++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format ordinal', function (assert) { + assert.equal(moment([2011, 0, 1]).format('DDDo'), '1', '1'); + assert.equal(moment([2011, 0, 2]).format('DDDo'), '2', '2'); + assert.equal(moment([2011, 0, 3]).format('DDDo'), '3', '3'); + assert.equal(moment([2011, 0, 4]).format('DDDo'), '4', '4'); + assert.equal(moment([2011, 0, 5]).format('DDDo'), '5', '5'); + assert.equal(moment([2011, 0, 6]).format('DDDo'), '6', '6'); + assert.equal(moment([2011, 0, 7]).format('DDDo'), '7', '7'); + assert.equal(moment([2011, 0, 8]).format('DDDo'), '8', '8'); + assert.equal(moment([2011, 0, 9]).format('DDDo'), '9', '9'); + assert.equal(moment([2011, 0, 10]).format('DDDo'), '10', '10'); + + assert.equal(moment([2011, 0, 11]).format('DDDo'), '11', '11'); + assert.equal(moment([2011, 0, 12]).format('DDDo'), '12', '12'); + assert.equal(moment([2011, 0, 13]).format('DDDo'), '13', '13'); + assert.equal(moment([2011, 0, 14]).format('DDDo'), '14', '14'); + assert.equal(moment([2011, 0, 15]).format('DDDo'), '15', '15'); + assert.equal(moment([2011, 0, 16]).format('DDDo'), '16', '16'); + assert.equal(moment([2011, 0, 17]).format('DDDo'), '17', '17'); + assert.equal(moment([2011, 0, 18]).format('DDDo'), '18', '18'); + assert.equal(moment([2011, 0, 19]).format('DDDo'), '19', '19'); + assert.equal(moment([2011, 0, 20]).format('DDDo'), '20', '20'); + + assert.equal(moment([2011, 0, 21]).format('DDDo'), '21', '21'); + assert.equal(moment([2011, 0, 22]).format('DDDo'), '22', '22'); + assert.equal(moment([2011, 0, 23]).format('DDDo'), '23', '23'); + assert.equal(moment([2011, 0, 24]).format('DDDo'), '24', '24'); + assert.equal(moment([2011, 0, 25]).format('DDDo'), '25', '25'); + assert.equal(moment([2011, 0, 26]).format('DDDo'), '26', '26'); + assert.equal(moment([2011, 0, 27]).format('DDDo'), '27', '27'); + assert.equal(moment([2011, 0, 28]).format('DDDo'), '28', '28'); + assert.equal(moment([2011, 0, 29]).format('DDDo'), '29', '29'); + assert.equal(moment([2011, 0, 30]).format('DDDo'), '30', '30'); + + assert.equal(moment([2011, 0, 31]).format('DDDo'), '31', '31'); + }); + + test('format month', function (assert) { + var i, + expected = 'tháng 1,Th01_tháng 2,Th02_tháng 3,Th03_tháng 4,Th04_tháng 5,Th05_tháng 6,Th06_tháng 7,Th07_tháng 8,Th08_tháng 9,Th09_tháng 10,Th10_tháng 11,Th11_tháng 12,Th12'.split('_'); + + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM,MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var i, + expected = 'chủ nhật CN CN_thứ hai T2 T2_thứ ba T3 T3_thứ tư T4 T4_thứ năm T5 T5_thứ sáu T6 T6_thứ bảy T7 T7'.split('_'); + + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), 'vài giây', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), 'một phút', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), 'một phút', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 phút', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 phút', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), 'một giờ', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), 'một giờ', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 giờ', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 giờ', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 giờ', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), 'một ngày', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), 'một ngày', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 ngày', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), 'một ngày', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 ngày', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 ngày', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), 'một tháng', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), 'một tháng', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), 'một tháng', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 tháng', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 tháng', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 tháng', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), 'một tháng', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 tháng', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), 'một năm', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 năm', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), 'một năm', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 năm', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), 'vài giây tới', 'prefix'); + assert.equal(moment(0).from(30000), 'vài giây trước', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), 'vài giây trước', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), 'vài giây tới', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), '5 ngày tới', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Hôm nay lúc 02:00', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Hôm nay lúc 02:25', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Hôm nay lúc 03:00', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Ngày mai lúc 02:00', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Hôm nay lúc 01:00', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Hôm qua lúc 02:00', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('dddd [tuần tới lúc] LT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [tuần tới lúc] LT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [tuần tới lúc] LT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('dddd [tuần rồi lúc] LT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('dddd [tuần rồi lúc] LT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('dddd [tuần rồi lúc] LT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 1, 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).week(), 2, 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 2, 'Jan 15 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 8]).week(), 2, 'Jan 8 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + assert.equal(moment([2007, 0, 15]).week(), 3, 'Jan 15 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).week(), 1, 'Dec 31 2007 should be week 1'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 7]).week(), 2, 'Jan 7 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + assert.equal(moment([2008, 0, 14]).week(), 3, 'Jan 14 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).week(), 1, 'Dec 30 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 6]).week(), 2, 'Jan 6 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + assert.equal(moment([2003, 0, 13]).week(), 3, 'Jan 13 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).week(), 1, 'Dec 29 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 5]).week(), 2, 'Jan 5 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + assert.equal(moment([2009, 0, 13]).week(), 3, 'Jan 12 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).week(), 53, 'Dec 28 2009 should be week 53'); + assert.equal(moment([2010, 0, 1]).week(), 53, 'Jan 1 2010 should be week 53'); + assert.equal(moment([2010, 0, 3]).week(), 53, 'Jan 3 2010 should be week 53'); + assert.equal(moment([2010, 0, 4]).week(), 1, 'Jan 4 2010 should be week 1'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + assert.equal(moment([2010, 0, 11]).week(), 2, 'Jan 11 2010 should be week 2'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).week(), 52, 'Dec 27 2010 should be week 52'); + assert.equal(moment([2011, 0, 1]).week(), 52, 'Jan 1 2011 should be week 52'); + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 3]).week(), 1, 'Jan 3 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + assert.equal(moment([2011, 0, 10]).week(), 2, 'Jan 10 2011 should be week 2'); + }); + + test('weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52', 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).format('w ww wo'), '1 01 1', 'Jan 2 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '1 01 1', 'Jan 8 2012 should be week 1'); + assert.equal(moment([2012, 0, 9]).format('w ww wo'), '2 02 2', 'Jan 9 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '2 02 2', 'Jan 15 2012 should be week 2'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('zh-cn'); + + test('parse', function (assert) { + var tests = '一月 1月_二月 2月_三月 3月_四月 4月_五月 5月_六月 6月_七月 7月_八月 8月_九月 9月_十月 10月_十一月 11月_十二月 12月'.split('_'), i; + + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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', '6 6周 06'], + ['h hh', '3 03'], + ['H HH', '15 15'], + ['m mm', '25 25'], + ['s ss', '50 50'], + ['a A', '下午 下午'], + ['[这年的第] DDDo', '这年的第 45日'], + ['LTS', '下午3点25分50秒'], + ['L', '2010-02-14'], + ['LL', '2010年2月14日'], + ['LLL', '2010年2月14日下午3点25分'], + ['LLLL', '2010年2月14日星期日下午3点25分'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format month', function (assert) { + var expected = '一月 1月_二月 2月_三月 3月_四月 4月_五月 5月_六月 6月_七月 7月_八月 8月_九月 9月_十月 10月_十一月 11月_十二月 12月'.split('_'), i; + + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = '星期日 周日 日_星期一 周一 一_星期二 周二 二_星期三 周三 三_星期四 周四 四_星期五 周五 五_星期六 周六 六'.split('_'), i; + + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), '几秒', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), '1 分钟', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), '1 分钟', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2 分钟', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44 分钟', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), '1 小时', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), '1 小时', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2 小时', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5 小时', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21 小时', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), '1 天', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), '1 天', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2 天', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), '1 天', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5 天', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25 天', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), '1 个月', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), '1 个月', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), '1 个月', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2 个月', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2 个月', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3 个月', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), '1 个月', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5 个月', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), '1 年', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2 年', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), '1 年', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5 年', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), '几秒内', 'prefix'); + assert.equal(moment(0).from(30000), '几秒前', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), '几秒前', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), '几秒内', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), '5 天内', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), '今天凌晨2点整', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), '今天凌晨2点25分', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), '今天凌晨3点整', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), '明天凌晨2点整', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), '今天凌晨1点整', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), '昨天凌晨2点整', 'yesterday at the same time'); + }); + + test('calendar current week', function (assert) { + var i, m, + today = moment().startOf('day'); + + for (i = 0; i < 7; i++) { + m = moment().startOf('week').add({d: i}); + if (Math.abs(m.diff(today, 'days')) <= 1) { + continue; // skip today, yesterday, tomorrow + } + assert.equal(m.calendar(), m.format('[本]ddd凌晨12点整'), 'Monday + ' + i + ' days current time'); + } + }); + + test('calendar next week', function (assert) { + var i, m, + today = moment().startOf('day'); + + for (i = 7; i < 14; i++) { + m = moment().startOf('week').add({d: i}); + if (Math.abs(m.diff(today, 'days')) >= 7) { + continue; + } + if (Math.abs(m.diff(today, 'days')) <= 1) { + continue; // skip today, yesterday, tomorrow + } + assert.equal(m.calendar(), m.format('[下]ddd凌晨12点整'), 'Today + ' + i + ' days beginning of day'); + } + assert.equal(42, 42, 'at least one assert'); + }); + + test('calendar last week', function (assert) { + var i, m, + today = moment().startOf('day'); + + for (i = 1; i < 8; i++) { + m = moment().startOf('week').subtract({d: i}); + if ((Math.abs(m.diff(today, 'days')) >= 7) || (Math.abs(m.diff(today, 'days')) <= 1)) { + continue; + } + assert.equal(m.calendar(), m.format('[上]ddd凌晨12点整'), 'Monday - ' + i + ' days next week'); + } + assert.equal(42, 42, 'at least one assert'); + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('LL'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('LL'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('LL'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('LL'), 'in 2 weeks'); + }); + + test('meridiem', function (assert) { + assert.equal(moment([2011, 2, 23, 0, 0]).format('A'), '凌晨', 'before dawn'); + assert.equal(moment([2011, 2, 23, 6, 0]).format('A'), '早上', 'morning'); + assert.equal(moment([2011, 2, 23, 9, 0]).format('A'), '上午', 'before noon'); + assert.equal(moment([2011, 2, 23, 12, 0]).format('A'), '中午', 'noon'); + assert.equal(moment([2011, 2, 23, 13, 0]).format('A'), '下午', 'afternoon'); + assert.equal(moment([2011, 2, 23, 18, 0]).format('A'), '晚上', 'night'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 52, 'Jan 1 2012 should be week 52'); + assert.equal(moment([2012, 0, 2]).week(), 1, 'Jan 2 2012 should be week 52'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 52, 'Dec 31 2006 should be week 52'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 1, 'Jan 7 2007 should be week 1'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 2, 'Jan 14 2007 should be week 2'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 1, 'Jan 6 2008 should be week 1'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 2, 'Jan 13 2008 should be week 2'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 52, 'Dec 29 2002 should be week 52'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 1, 'Jan 5 2003 should be week 1'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 2, 'Jan 12 2003 should be week 2'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 1, 'Jan 4 2009 should be week 1'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 2, 'Jan 11 2009 should be week 2'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2010, 0, 2]).week(), 53, 'Jan 2 2010 should be week 53'); + assert.equal(moment([2010, 0, 10]).week(), 1, 'Jan 10 2010 should be week 1'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2011, 0, 2]).week(), 52, 'Jan 2 2011 should be week 52'); + assert.equal(moment([2011, 0, 8]).week(), 1, 'Jan 8 2011 should be week 1'); + assert.equal(moment([2011, 0, 9]).week(), 1, 'Jan 9 2011 should be week 1'); + }); + + test('weeks year starting sunday format', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '52 52 52周', 'Jan 1 2012 应该是第52周'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1周', 'Jan 7 2012 应该是第 1周'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2周', 'Jan 14 2012 应该是第 2周'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('meridiem invariant', function (assert) { + var h, m, t1, t2; + for (h = 0; h < 24; ++h) { + for (m = 0; m < 60; m += 15) { + t1 = moment.utc([2000, 0, 1, h, m]); + t2 = moment(t1.format('A h:mm'), 'A h:mm'); + assert.equal(t2.format('HH:mm'), t1.format('HH:mm'), + 'meridiem at ' + t1.format('HH:mm')); + } + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + localeModule('zh-tw'); + + test('parse', function (assert) { + var tests = '一月 1月_二月 2月_三月 3月_四月 4月_五月 5月_六月 6月_七月 7月_八月 8月_九月 9月_十月 10月_十一月 11月_十二月 12月'.split('_'), i; + function equalTest(input, mmm, i) { + assert.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('format', function (assert) { + 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日'], + ['LTS', '下午3點25分50秒'], + ['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++) { + assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('format month', function (assert) { + var expected = '一月 1月_二月 2月_三月 3月_四月 4月_五月 5月_六月 6月_七月 7月_八月 8月_九月 9月_十月 10月_十一月 11月_十二月 12月'.split('_'), i; + + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, i, 1]).format('MMMM MMM'), expected[i], expected[i]); + } + }); + + test('format week', function (assert) { + var expected = '星期日 週日 日_星期一 週一 一_星期二 週二 二_星期三 週三 三_星期四 週四 四_星期五 週五 五_星期六 週六 六'.split('_'), i; + + for (i = 0; i < expected.length; i++) { + assert.equal(moment([2011, 0, 2 + i]).format('dddd ddd dd'), expected[i], expected[i]); + } + }); + + test('from', function (assert) { + var start = moment([2007, 1, 28]); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44}), true), '幾秒', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45}), true), '一分鐘', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89}), true), '一分鐘', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '2分鐘', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44}), true), '44分鐘', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45}), true), '一小時', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89}), true), '一小時', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90}), true), '2小時', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5}), true), '5小時', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21}), true), '21小時', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22}), true), '一天', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35}), true), '一天', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36}), true), '2天', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1}), true), '一天', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5}), true), '5天', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25}), true), '25天', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26}), true), '一個月', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30}), true), '一個月', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43}), true), '一個月', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46}), true), '2個月', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74}), true), '2個月', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76}), true), '3個月', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1}), true), '一個月', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5}), true), '5個月', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345}), true), '一年', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548}), true), '2年', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1}), true), '一年', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5}), true), '5年', '5 years = 5 years'); + }); + + test('suffix', function (assert) { + assert.equal(moment(30000).from(0), '幾秒內', 'prefix'); + assert.equal(moment(0).from(30000), '幾秒前', 'suffix'); + }); + + test('now from now', function (assert) { + assert.equal(moment().fromNow(), '幾秒前', 'now from now should display as in the past'); + }); + + test('fromNow', function (assert) { + assert.equal(moment().add({s: 30}).fromNow(), '幾秒內', 'in a few seconds'); + assert.equal(moment().add({d: 5}).fromNow(), '5天內', 'in 5 days'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), '今天早上2點00分', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), '今天早上2點25分', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), '今天早上3點00分', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), '明天早上2點00分', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), '今天早上1點00分', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), '昨天早上2點00分', 'yesterday at the same time'); + }); + + test('calendar next week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().add({d: i}); + assert.equal(m.calendar(), m.format('[下]ddddLT'), 'Today + ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[下]ddddLT'), 'Today + ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[下]ddddLT'), 'Today + ' + i + ' days end of day'); + } + }); + + test('calendar last week', function (assert) { + var i, m; + for (i = 2; i < 7; i++) { + m = moment().subtract({d: i}); + assert.equal(m.calendar(), m.format('[上]ddddLT'), 'Today - ' + i + ' days current time'); + m.hours(0).minutes(0).seconds(0).milliseconds(0); + assert.equal(m.calendar(), m.format('[上]ddddLT'), 'Today - ' + i + ' days beginning of day'); + m.hours(23).minutes(59).seconds(59).milliseconds(999); + assert.equal(m.calendar(), m.format('[上]ddddLT'), 'Today - ' + i + ' days end of day'); + } + }); + + test('calendar all else', function (assert) { + var weeksAgo = moment().subtract({w: 1}), + weeksFromNow = moment().add({w: 1}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week'); + + weeksAgo = moment().subtract({w: 2}); + weeksFromNow = moment().add({w: 2}); + + assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago'); + assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks'); + }); + + test('meridiem', function (assert) { + assert.equal(moment([2011, 2, 23, 0, 0]).format('a'), '早上', 'morning'); + assert.equal(moment([2011, 2, 23, 9, 0]).format('a'), '上午', 'before noon'); + assert.equal(moment([2011, 2, 23, 12, 0]).format('a'), '中午', 'noon'); + assert.equal(moment([2011, 2, 23, 13, 0]).format('a'), '下午', 'after noon'); + assert.equal(moment([2011, 2, 23, 18, 0]).format('a'), '晚上', 'night'); + + assert.equal(moment([2011, 2, 23, 0, 0]).format('A'), '早上', 'morning'); + assert.equal(moment([2011, 2, 23, 9, 0]).format('A'), '上午', 'before noon'); + assert.equal(moment([2011, 2, 23, 12, 0]).format('A'), '中午', 'noon'); + assert.equal(moment([2011, 2, 23, 13, 0]).format('A'), '下午', 'afternoon'); + assert.equal(moment([2011, 2, 23, 18, 0]).format('A'), '晚上', 'night'); + }); + + test('weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).week(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).week(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).week(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).week(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).week(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('weeks year starting monday', function (assert) { + assert.equal(moment([2006, 11, 31]).week(), 1, 'Dec 31 2006 should be week 1'); + assert.equal(moment([2007, 0, 1]).week(), 1, 'Jan 1 2007 should be week 1'); + assert.equal(moment([2007, 0, 6]).week(), 1, 'Jan 6 2007 should be week 1'); + assert.equal(moment([2007, 0, 7]).week(), 2, 'Jan 7 2007 should be week 2'); + assert.equal(moment([2007, 0, 13]).week(), 2, 'Jan 13 2007 should be week 2'); + assert.equal(moment([2007, 0, 14]).week(), 3, 'Jan 14 2007 should be week 3'); + }); + + test('weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 29]).week(), 52, 'Dec 29 2007 should be week 52'); + assert.equal(moment([2008, 0, 1]).week(), 1, 'Jan 1 2008 should be week 1'); + assert.equal(moment([2008, 0, 5]).week(), 1, 'Jan 5 2008 should be week 1'); + assert.equal(moment([2008, 0, 6]).week(), 2, 'Jan 6 2008 should be week 2'); + assert.equal(moment([2008, 0, 12]).week(), 2, 'Jan 12 2008 should be week 2'); + assert.equal(moment([2008, 0, 13]).week(), 3, 'Jan 13 2008 should be week 3'); + }); + + test('weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 29]).week(), 1, 'Dec 29 2002 should be week 1'); + assert.equal(moment([2003, 0, 1]).week(), 1, 'Jan 1 2003 should be week 1'); + assert.equal(moment([2003, 0, 4]).week(), 1, 'Jan 4 2003 should be week 1'); + assert.equal(moment([2003, 0, 5]).week(), 2, 'Jan 5 2003 should be week 2'); + assert.equal(moment([2003, 0, 11]).week(), 2, 'Jan 11 2003 should be week 2'); + assert.equal(moment([2003, 0, 12]).week(), 3, 'Jan 12 2003 should be week 3'); + }); + + test('weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 28]).week(), 1, 'Dec 28 2008 should be week 1'); + assert.equal(moment([2009, 0, 1]).week(), 1, 'Jan 1 2009 should be week 1'); + assert.equal(moment([2009, 0, 3]).week(), 1, 'Jan 3 2009 should be week 1'); + assert.equal(moment([2009, 0, 4]).week(), 2, 'Jan 4 2009 should be week 2'); + assert.equal(moment([2009, 0, 10]).week(), 2, 'Jan 10 2009 should be week 2'); + assert.equal(moment([2009, 0, 11]).week(), 3, 'Jan 11 2009 should be week 3'); + }); + + test('weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 27]).week(), 1, 'Dec 27 2009 should be week 1'); + assert.equal(moment([2010, 0, 1]).week(), 1, 'Jan 1 2010 should be week 1'); + assert.equal(moment([2010, 0, 2]).week(), 1, 'Jan 2 2010 should be week 1'); + assert.equal(moment([2010, 0, 3]).week(), 2, 'Jan 3 2010 should be week 2'); + assert.equal(moment([2010, 0, 9]).week(), 2, 'Jan 9 2010 should be week 2'); + assert.equal(moment([2010, 0, 10]).week(), 3, 'Jan 10 2010 should be week 3'); + }); + + test('weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 26]).week(), 1, 'Dec 26 2010 should be week 1'); + assert.equal(moment([2011, 0, 1]).week(), 1, 'Jan 1 2011 should be week 1'); + assert.equal(moment([2011, 0, 2]).week(), 2, 'Jan 2 2011 should be week 2'); + assert.equal(moment([2011, 0, 8]).week(), 2, 'Jan 8 2011 should be week 2'); + assert.equal(moment([2011, 0, 9]).week(), 3, 'Jan 9 2011 should be week 3'); + }); + + test('weeks year starting sunday format', function (assert) { + assert.equal(moment([2012, 0, 1]).format('w ww wo'), '1 01 1週', 'Jan 1 2012 應該是第 1週'); + assert.equal(moment([2012, 0, 7]).format('w ww wo'), '1 01 1週', 'Jan 7 2012 應該是第 1週'); + assert.equal(moment([2012, 0, 8]).format('w ww wo'), '2 02 2週', 'Jan 8 2012 應該是第 2週'); + assert.equal(moment([2012, 0, 14]).format('w ww wo'), '2 02 2週', 'Jan 14 2012 應該是第 2週'); + assert.equal(moment([2012, 0, 15]).format('w ww wo'), '3 03 3週', 'Jan 15 2012 應該是第 3週'); + }); + + test('lenient ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing ' + i + ' date check'); + } + }); + + test('lenient ordinal parsing of number', function (assert) { + var i, testMoment; + for (i = 1; i <= 31; ++i) { + testMoment = moment('2014 01 ' + i, 'YYYY MM Do'); + assert.equal(testMoment.year(), 2014, + 'lenient ordinal parsing of number ' + i + ' year check'); + assert.equal(testMoment.month(), 0, + 'lenient ordinal parsing of number ' + i + ' month check'); + assert.equal(testMoment.date(), i, + 'lenient ordinal parsing of number ' + i + ' date check'); + } + }); + + test('meridiem invariant', function (assert) { + var h, m, t1, t2; + for (h = 0; h < 24; ++h) { + for (m = 0; m < 60; m += 15) { + t1 = moment.utc([2000, 0, 1, h, m]); + t2 = moment(t1.format('A h:mm'), 'A h:mm'); + assert.equal(t2.format('HH:mm'), t1.format('HH:mm'), + 'meridiem at ' + t1.format('HH:mm')); + } + } + }); + + test('strict ordinal parsing', function (assert) { + var i, ordinalStr, testMoment; + for (i = 1; i <= 31; ++i) { + ordinalStr = moment([2014, 0, i]).format('YYYY MM Do'); + testMoment = moment(ordinalStr, 'YYYY MM Do', true); + assert.ok(testMoment.isValid(), 'strict ordinal parsing ' + i); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('add and subtract'); + + test('add short reverse args', function (assert) { + var a = moment(), b, c, d; + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + assert.equal(a.add({ms: 50}).milliseconds(), 550, 'Add milliseconds'); + assert.equal(a.add({s: 1}).seconds(), 9, 'Add seconds'); + assert.equal(a.add({m: 1}).minutes(), 8, 'Add minutes'); + assert.equal(a.add({h: 1}).hours(), 7, 'Add hours'); + assert.equal(a.add({d: 1}).date(), 13, 'Add date'); + assert.equal(a.add({w: 1}).date(), 20, 'Add week'); + assert.equal(a.add({M: 1}).month(), 10, 'Add month'); + assert.equal(a.add({y: 1}).year(), 2012, 'Add year'); + assert.equal(a.add({Q: 1}).month(), 1, 'Add quarter'); + + b = moment([2010, 0, 31]).add({M: 1}); + c = moment([2010, 1, 28]).subtract({M: 1}); + d = moment([2010, 1, 28]).subtract({Q: 1}); + + assert.equal(b.month(), 1, 'add month, jan 31st to feb 28th'); + assert.equal(b.date(), 28, 'add month, jan 31st to feb 28th'); + assert.equal(c.month(), 0, 'subtract month, feb 28th to jan 28th'); + assert.equal(c.date(), 28, 'subtract month, feb 28th to jan 28th'); + assert.equal(d.month(), 10, 'subtract quarter, feb 28th 2010 to nov 28th 2009'); + assert.equal(d.date(), 28, 'subtract quarter, feb 28th 2010 to nov 28th 2009'); + assert.equal(d.year(), 2009, 'subtract quarter, feb 28th 2010 to nov 28th 2009'); + }); + + test('add long reverse args', function (assert) { + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + assert.equal(a.add({milliseconds: 50}).milliseconds(), 550, 'Add milliseconds'); + assert.equal(a.add({seconds: 1}).seconds(), 9, 'Add seconds'); + assert.equal(a.add({minutes: 1}).minutes(), 8, 'Add minutes'); + assert.equal(a.add({hours: 1}).hours(), 7, 'Add hours'); + assert.equal(a.add({days: 1}).date(), 13, 'Add date'); + assert.equal(a.add({weeks: 1}).date(), 20, 'Add week'); + assert.equal(a.add({months: 1}).month(), 10, 'Add month'); + assert.equal(a.add({years: 1}).year(), 2012, 'Add year'); + assert.equal(a.add({quarters: 1}).month(), 1, 'Add quarter'); + }); + + test('add long singular reverse args', function (assert) { + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + assert.equal(a.add({millisecond: 50}).milliseconds(), 550, 'Add milliseconds'); + assert.equal(a.add({second: 1}).seconds(), 9, 'Add seconds'); + assert.equal(a.add({minute: 1}).minutes(), 8, 'Add minutes'); + assert.equal(a.add({hour: 1}).hours(), 7, 'Add hours'); + assert.equal(a.add({day: 1}).date(), 13, 'Add date'); + assert.equal(a.add({week: 1}).date(), 20, 'Add week'); + assert.equal(a.add({month: 1}).month(), 10, 'Add month'); + assert.equal(a.add({year: 1}).year(), 2012, 'Add year'); + assert.equal(a.add({quarter: 1}).month(), 1, 'Add quarter'); + }); + + test('add string long reverse args', function (assert) { + var a = moment(), b; + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + b = a.clone(); + + assert.equal(a.add('millisecond', 50).milliseconds(), 550, 'Add milliseconds'); + assert.equal(a.add('second', 1).seconds(), 9, 'Add seconds'); + assert.equal(a.add('minute', 1).minutes(), 8, 'Add minutes'); + assert.equal(a.add('hour', 1).hours(), 7, 'Add hours'); + assert.equal(a.add('day', 1).date(), 13, 'Add date'); + assert.equal(a.add('week', 1).date(), 20, 'Add week'); + assert.equal(a.add('month', 1).month(), 10, 'Add month'); + assert.equal(a.add('year', 1).year(), 2012, 'Add year'); + assert.equal(b.add('day', '01').date(), 13, 'Add date'); + assert.equal(a.add('quarter', 1).month(), 1, 'Add quarter'); + }); + + test('add string long singular reverse args', function (assert) { + var a = moment(), b; + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + b = a.clone(); + + assert.equal(a.add('milliseconds', 50).milliseconds(), 550, 'Add milliseconds'); + assert.equal(a.add('seconds', 1).seconds(), 9, 'Add seconds'); + assert.equal(a.add('minutes', 1).minutes(), 8, 'Add minutes'); + assert.equal(a.add('hours', 1).hours(), 7, 'Add hours'); + assert.equal(a.add('days', 1).date(), 13, 'Add date'); + assert.equal(a.add('weeks', 1).date(), 20, 'Add week'); + assert.equal(a.add('months', 1).month(), 10, 'Add month'); + assert.equal(a.add('years', 1).year(), 2012, 'Add year'); + assert.equal(b.add('days', '01').date(), 13, 'Add date'); + assert.equal(a.add('quarters', 1).month(), 1, 'Add quarter'); + }); + + test('add string short reverse args', function (assert) { + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + assert.equal(a.add('ms', 50).milliseconds(), 550, 'Add milliseconds'); + assert.equal(a.add('s', 1).seconds(), 9, 'Add seconds'); + assert.equal(a.add('m', 1).minutes(), 8, 'Add minutes'); + assert.equal(a.add('h', 1).hours(), 7, 'Add hours'); + assert.equal(a.add('d', 1).date(), 13, 'Add date'); + assert.equal(a.add('w', 1).date(), 20, 'Add week'); + assert.equal(a.add('M', 1).month(), 10, 'Add month'); + assert.equal(a.add('y', 1).year(), 2012, 'Add year'); + assert.equal(a.add('Q', 1).month(), 1, 'Add quarter'); + }); + + test('add string long', function (assert) { + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + assert.equal(a.add(50, 'millisecond').milliseconds(), 550, 'Add milliseconds'); + assert.equal(a.add(1, 'second').seconds(), 9, 'Add seconds'); + assert.equal(a.add(1, 'minute').minutes(), 8, 'Add minutes'); + assert.equal(a.add(1, 'hour').hours(), 7, 'Add hours'); + assert.equal(a.add(1, 'day').date(), 13, 'Add date'); + assert.equal(a.add(1, 'week').date(), 20, 'Add week'); + assert.equal(a.add(1, 'month').month(), 10, 'Add month'); + assert.equal(a.add(1, 'year').year(), 2012, 'Add year'); + assert.equal(a.add(1, 'quarter').month(), 1, 'Add quarter'); + }); + + test('add string long singular', function (assert) { + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + assert.equal(a.add(50, 'milliseconds').milliseconds(), 550, 'Add milliseconds'); + assert.equal(a.add(1, 'seconds').seconds(), 9, 'Add seconds'); + assert.equal(a.add(1, 'minutes').minutes(), 8, 'Add minutes'); + assert.equal(a.add(1, 'hours').hours(), 7, 'Add hours'); + assert.equal(a.add(1, 'days').date(), 13, 'Add date'); + assert.equal(a.add(1, 'weeks').date(), 20, 'Add week'); + assert.equal(a.add(1, 'months').month(), 10, 'Add month'); + assert.equal(a.add(1, 'years').year(), 2012, 'Add year'); + assert.equal(a.add(1, 'quarters').month(), 1, 'Add quarter'); + }); + + test('add string short', function (assert) { + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + assert.equal(a.add(50, 'ms').milliseconds(), 550, 'Add milliseconds'); + assert.equal(a.add(1, 's').seconds(), 9, 'Add seconds'); + assert.equal(a.add(1, 'm').minutes(), 8, 'Add minutes'); + assert.equal(a.add(1, 'h').hours(), 7, 'Add hours'); + assert.equal(a.add(1, 'd').date(), 13, 'Add date'); + assert.equal(a.add(1, 'w').date(), 20, 'Add week'); + assert.equal(a.add(1, 'M').month(), 10, 'Add month'); + assert.equal(a.add(1, 'y').year(), 2012, 'Add year'); + assert.equal(a.add(1, 'Q').month(), 1, 'Add quarter'); + }); + + test('add strings string short args', function (assert) { + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + assert.equal(a.add('ms', '50').milliseconds(), 550, 'Add milliseconds'); + assert.equal(a.add('s', '1').seconds(), 9, 'Add seconds'); + assert.equal(a.add('m', '1').minutes(), 8, 'Add minutes'); + assert.equal(a.add('h', '1').hours(), 7, 'Add hours'); + assert.equal(a.add('d', '1').date(), 13, 'Add date'); + assert.equal(a.add('w', '1').date(), 20, 'Add week'); + assert.equal(a.add('M', '1').month(), 10, 'Add month'); + assert.equal(a.add('y', '1').year(), 2012, 'Add year'); + assert.equal(a.add('Q', '1').month(), 1, 'Add quarter'); + }); + + test('subtract strings string short args', function (assert) { + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + assert.equal(a.subtract('ms', '50').milliseconds(), 450, 'Subtract milliseconds'); + assert.equal(a.subtract('s', '1').seconds(), 7, 'Subtract seconds'); + assert.equal(a.subtract('m', '1').minutes(), 6, 'Subtract minutes'); + assert.equal(a.subtract('h', '1').hours(), 5, 'Subtract hours'); + assert.equal(a.subtract('d', '1').date(), 11, 'Subtract date'); + assert.equal(a.subtract('w', '1').date(), 4, 'Subtract week'); + assert.equal(a.subtract('M', '1').month(), 8, 'Subtract month'); + assert.equal(a.subtract('y', '1').year(), 2010, 'Subtract year'); + assert.equal(a.subtract('Q', '1').month(), 5, 'Subtract quarter'); + }); + + test('add strings string short', function (assert) { + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + assert.equal(a.add('50', 'ms').milliseconds(), 550, 'Add milliseconds'); + assert.equal(a.add('1', 's').seconds(), 9, 'Add seconds'); + assert.equal(a.add('1', 'm').minutes(), 8, 'Add minutes'); + assert.equal(a.add('1', 'h').hours(), 7, 'Add hours'); + assert.equal(a.add('1', 'd').date(), 13, 'Add date'); + assert.equal(a.add('1', 'w').date(), 20, 'Add week'); + assert.equal(a.add('1', 'M').month(), 10, 'Add month'); + assert.equal(a.add('1', 'y').year(), 2012, 'Add year'); + assert.equal(a.add('1', 'Q').month(), 1, 'Add quarter'); + }); + + test('subtract strings string short', function (assert) { + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(500); + + assert.equal(a.subtract('50', 'ms').milliseconds(), 450, 'Subtract milliseconds'); + assert.equal(a.subtract('1', 's').seconds(), 7, 'Subtract seconds'); + assert.equal(a.subtract('1', 'm').minutes(), 6, 'Subtract minutes'); + assert.equal(a.subtract('1', 'h').hours(), 5, 'Subtract hours'); + assert.equal(a.subtract('1', 'd').date(), 11, 'Subtract date'); + assert.equal(a.subtract('1', 'w').date(), 4, 'Subtract week'); + assert.equal(a.subtract('1', 'M').month(), 8, 'Subtract month'); + assert.equal(a.subtract('1', 'y').year(), 2010, 'Subtract year'); + assert.equal(a.subtract('1', 'Q').month(), 5, 'Subtract quarter'); + }); + + test('add across DST', function (assert) { + // Detect Safari bug and bail. Hours on 13th March 2011 are shifted + // with 1 ahead. + if (new Date(2011, 2, 13, 5, 0, 0).getHours() !== 5) { + return; + } + + var a = moment(new Date(2011, 2, 12, 5, 0, 0)), + b = moment(new Date(2011, 2, 12, 5, 0, 0)), + c = moment(new Date(2011, 2, 12, 5, 0, 0)), + d = moment(new Date(2011, 2, 12, 5, 0, 0)), + e = moment(new Date(2011, 2, 12, 5, 0, 0)); + a.add(1, 'days'); + b.add(24, 'hours'); + c.add(1, 'months'); + e.add(1, 'quarter'); + + assert.equal(a.hours(), 5, 'adding days over DST difference should result in the same hour'); + if (b.isDST() && !d.isDST()) { + assert.equal(b.hours(), 6, 'adding hours over DST difference should result in a different hour'); + } else if (!b.isDST() && d.isDST()) { + assert.equal(b.hours(), 4, 'adding hours over DST difference should result in a different hour'); + } else { + assert.equal(b.hours(), 5, 'adding hours over DST difference should result in a same hour if the timezone does not have daylight savings time'); + } + assert.equal(c.hours(), 5, 'adding months over DST difference should result in the same hour'); + assert.equal(e.hours(), 5, 'adding quarters over DST difference should result in the same hour'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('create'); + + test('array', function (assert) { + assert.ok(moment([2010]).toDate() instanceof Date, '[2010]'); + assert.ok(moment([2010, 1]).toDate() instanceof Date, '[2010, 1]'); + assert.ok(moment([2010, 1, 12]).toDate() instanceof Date, '[2010, 1, 12]'); + assert.ok(moment([2010, 1, 12, 1]).toDate() instanceof Date, '[2010, 1, 12, 1]'); + assert.ok(moment([2010, 1, 12, 1, 1]).toDate() instanceof Date, '[2010, 1, 12, 1, 1]'); + assert.ok(moment([2010, 1, 12, 1, 1, 1]).toDate() instanceof Date, '[2010, 1, 12, 1, 1, 1]'); + assert.ok(moment([2010, 1, 12, 1, 1, 1, 1]).toDate() instanceof Date, '[2010, 1, 12, 1, 1, 1, 1]'); + assert.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('array copying', function (assert) { + var importantArray = [2009, 11]; + moment(importantArray); + assert.deepEqual(importantArray, [2009, 11], 'initializer should not mutate the original array'); + }); + + test('object', function (assert) { + var fmt = 'YYYY-MM-DD HH:mm:ss.SSS', + tests = [ + [{year: 2010}, '2010-01-01 00:00:00.000'], + [{year: 2010, month: 1}, '2010-02-01 00:00:00.000'], + [{year: 2010, month: 1, day: 12}, '2010-02-12 00:00:00.000'], + [{year: 2010, month: 1, date: 12}, '2010-02-12 00:00:00.000'], + [{year: 2010, month: 1, day: 12, hours: 1}, '2010-02-12 01:00:00.000'], + [{year: 2010, month: 1, date: 12, hours: 1}, '2010-02-12 01:00:00.000'], + [{year: 2010, month: 1, day: 12, hours: 1, minutes: 1}, '2010-02-12 01:01:00.000'], + [{year: 2010, month: 1, date: 12, hours: 1, minutes: 1}, '2010-02-12 01:01:00.000'], + [{year: 2010, month: 1, day: 12, hours: 1, minutes: 1, seconds: 1}, '2010-02-12 01:01:01.000'], + [{year: 2010, month: 1, day: 12, hours: 1, minutes: 1, seconds: 1, milliseconds: 1}, '2010-02-12 01:01:01.001'], + [{years: 2010, months: 1, days: 14, hours: 15, minutes: 25, seconds: 50, milliseconds: 125}, '2010-02-14 15:25:50.125'], + [{year: 2010, month: 1, day: 14, hour: 15, minute: 25, second: 50, millisecond: 125}, '2010-02-14 15:25:50.125'], + [{y: 2010, M: 1, d: 14, h: 15, m: 25, s: 50, ms: 125}, '2010-02-14 15:25:50.125'] + ], i; + for (i = 0; i < tests.length; ++i) { + assert.equal(moment(tests[i][0]).format(fmt), tests[i][1]); + } + }); + + test('multi format array copying', function (assert) { + var importantArray = ['MM/DD/YYYY', 'YYYY-MM-DD', 'MM-DD-YYYY']; + moment('1999-02-13', importantArray); + assert.deepEqual(importantArray, ['MM/DD/YYYY', 'YYYY-MM-DD', 'MM-DD-YYYY'], 'initializer should not mutate the original array'); + }); + + test('number', function (assert) { + assert.ok(moment(1000).toDate() instanceof Date, '1000'); + assert.equal(moment(1000).valueOf(), 1000, 'asserting valueOf'); + assert.equal(moment.utc(1000).valueOf(), 1000, 'asserting valueOf'); + }); + + test('unix', function (assert) { + assert.equal(moment.unix(1).valueOf(), 1000, '1 unix timestamp == 1000 Date.valueOf'); + assert.equal(moment(1000).unix(), 1, '1000 Date.valueOf == 1 unix timestamp'); + assert.equal(moment.unix(1000).valueOf(), 1000000, '1000 unix timestamp == 1000000 Date.valueOf'); + assert.equal(moment(1500).unix(), 1, '1500 Date.valueOf == 1 unix timestamp'); + assert.equal(moment(1900).unix(), 1, '1900 Date.valueOf == 1 unix timestamp'); + assert.equal(moment(2100).unix(), 2, '2100 Date.valueOf == 2 unix timestamp'); + assert.equal(moment(1333129333524).unix(), 1333129333, '1333129333524 Date.valueOf == 1333129333 unix timestamp'); + assert.equal(moment(1333129333524000).unix(), 1333129333524, '1333129333524000 Date.valueOf == 1333129333524 unix timestamp'); + }); + + test('date', function (assert) { + assert.ok(moment(new Date()).toDate() instanceof Date, 'new Date()'); + }); + + test('date mutation', function (assert) { + var a = new Date(); + assert.ok(moment(a).toDate() !== a, 'the date moment uses should not be the date passed in'); + }); + + test('moment', function (assert) { + assert.ok(moment(moment()).toDate() instanceof Date, 'moment(moment())'); + assert.ok(moment(moment(moment())).toDate() instanceof Date, 'moment(moment(moment()))'); + }); + + test('cloning moment should only copy own properties', function (assert) { + assert.ok(!moment().clone().hasOwnProperty('month'), 'Should not clone prototype methods'); + }); + + test('cloning moment works with weird clones', function (assert) { + var extend = function (a, b) { + var i; + for (i in b) { + a[i] = b[i]; + } + return a; + }, + now = moment(), + nowu = moment.utc(); + + assert.equal(+extend({}, now).clone(), +now, 'cloning extend-ed now is now'); + assert.equal(+extend({}, nowu).clone(), +nowu, 'cloning extend-ed utc now is utc now'); + }); + + test('cloning respects moment.momentProperties', function (assert) { + var m = moment(); + + assert.equal(m.clone()._special, undefined, 'cloning ignores extra properties'); + m._special = 'bacon'; + moment.momentProperties.push('_special'); + assert.equal(m.clone()._special, 'bacon', 'cloning respects momentProperties'); + moment.momentProperties.pop(); + }); + + test('undefined', function (assert) { + assert.ok(moment().toDate() instanceof Date, 'undefined'); + }); + + test('iso format 24hrs', function (assert) { + assert.equal(moment('2014-01-01T24:00:00.000').format('YYYY-MM-DD[T]HH:mm:ss.SSS'), + '2014-01-02T00:00:00.000', 'iso format with 24:00 localtime'); + assert.equal(moment.utc('2014-01-01T24:00:00.000').format('YYYY-MM-DD[T]HH:mm:ss.SSS'), + '2014-01-02T00:00:00.000', 'iso format with 24:00 utc'); + }); + + test('string without format - json', function (assert) { + assert.equal(moment('Date(1325132654000)').valueOf(), 1325132654000, 'Date(1325132654000)'); + assert.equal(moment('Date(-1325132654000)').valueOf(), -1325132654000, 'Date(-1325132654000)'); + assert.equal(moment('/Date(1325132654000)/').valueOf(), 1325132654000, '/Date(1325132654000)/'); + assert.equal(moment('/Date(1325132654000+0700)/').valueOf(), 1325132654000, '/Date(1325132654000+0700)/'); + assert.equal(moment('/Date(1325132654000-0700)/').valueOf(), 1325132654000, '/Date(1325132654000-0700)/'); + }); + + test('string with format dropped am/pm bug', function (assert) { + moment.locale('en'); + + assert.equal(moment('05/1/2012 12:25:00', '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'); + assert.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'); + assert.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'); + + assert.ok(moment('05/1/2012 12:25:00', 'MM/DD/YYYY h:m:s a').isValid()); + assert.ok(moment('05/1/2012 12:25:00 am', 'MM/DD/YYYY h:m:s a').isValid()); + assert.ok(moment('05/1/2012 12:25:00 pm', 'MM/DD/YYYY h:m:s a').isValid()); + }); + + test('empty string with formats', function (assert) { + assert.equal(moment('', 'MM').format('YYYY-MM-DD HH:mm:ss'), 'Invalid date'); + assert.equal(moment(' ', 'MM').format('YYYY-MM-DD HH:mm:ss'), 'Invalid date'); + assert.equal(moment(' ', 'DD').format('YYYY-MM-DD HH:mm:ss'), 'Invalid date'); + assert.equal(moment(' ', ['MM', 'DD']).format('YYYY-MM-DD HH:mm:ss'), 'Invalid date'); + + assert.ok(!moment('', 'MM').isValid()); + assert.ok(!moment(' ', 'MM').isValid()); + assert.ok(!moment(' ', 'DD').isValid()); + assert.ok(!moment(' ', ['MM', 'DD']).isValid()); + }); + + test('defaulting to current date', function (assert) { + var now = moment(); + assert.equal(moment('12:13:14', 'hh:mm:ss').format('YYYY-MM-DD hh:mm:ss'), + now.clone().hour(12).minute(13).second(14).format('YYYY-MM-DD hh:mm:ss'), + 'given only time default to current date'); + assert.equal(moment('05', 'DD').format('YYYY-MM-DD'), + now.clone().date(5).format('YYYY-MM-DD'), + 'given day of month default to current month, year'); + assert.equal(moment('05', 'MM').format('YYYY-MM-DD'), + now.clone().month(4).date(1).format('YYYY-MM-DD'), + 'given month default to current year'); + assert.equal(moment('1996', 'YYYY').format('YYYY-MM-DD'), + now.clone().year(1996).month(0).date(1).format('YYYY-MM-DD'), + 'given year do not default'); + }); + + test('matching am/pm', function (assert) { + assert.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'); + assert.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.'); + assert.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'); + assert.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'); + assert.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.'); + assert.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'); + + assert.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'); + assert.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.'); + assert.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'); + assert.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'); + assert.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.'); + assert.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'); + + assert.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('string with format', function (assert) { + moment.locale('en'); + var a = [ + ['YYYY-Q', '2014-4'], + ['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', '1234567890'], + ['x', '1234567890123'], + ['LT', '12:30 AM'], + ['LTS', '12:30:29 AM'], + ['L', '09/02/1999'], + ['l', '9/2/1999'], + ['LL', 'September 2, 1999'], + ['ll', 'Sep 2, 1999'], + ['LLL', 'September 2, 1999 12:30 AM'], + ['lll', 'Sep 2, 1999 12:30 AM'], + ['LLLL', 'Thursday, September 2, 1999 12:30 AM'], + ['llll', 'Thu, Sep 2, 1999 12:30 AM'] + ], + m, + i; + + for (i = 0; i < a.length; i++) { + m = moment(a[i][1], a[i][0]); + assert.ok(m.isValid()); + assert.equal(m.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('unix timestamp format', function (assert) { + var formats = ['X', 'X.S', 'X.SS', 'X.SSS'], i, format; + + for (i = 0; i < formats.length; i++) { + format = formats[i]; + assert.equal(moment('1234567890', format).valueOf(), 1234567890 * 1000, format + ' matches timestamp without milliseconds'); + assert.equal(moment('1234567890.1', format).valueOf(), 1234567890 * 1000 + 100, format + ' matches timestamp with deciseconds'); + assert.equal(moment('1234567890.12', format).valueOf(), 1234567890 * 1000 + 120, format + ' matches timestamp with centiseconds'); + assert.equal(moment('1234567890.123', format).valueOf(), 1234567890 * 1000 + 123, format + ' matches timestamp with milliseconds'); + } + }); + + test('unix offset milliseconds', function (assert) { + assert.equal(moment('1234567890123', 'x').valueOf(), 1234567890123, 'x matches unix offset in milliseconds'); + }); + + test('milliseconds format', function (assert) { + assert.equal(moment('1', 'S').get('ms'), 100, 'deciseconds'); + // assert.equal(moment('10', 'S', true).isValid(), false, 'deciseconds with two digits'); + // assert.equal(moment('1', 'SS', true).isValid(), false, 'centiseconds with one digits'); + assert.equal(moment('12', 'SS').get('ms'), 120, 'centiseconds'); + // assert.equal(moment('123', 'SS', true).isValid(), false, 'centiseconds with three digits'); + assert.equal(moment('123', 'SSS').get('ms'), 123, 'milliseconds'); + assert.equal(moment('1234', 'SSSS').get('ms'), 123, 'milliseconds with SSSS'); + assert.equal(moment('123456789101112', 'SSSS').get('ms'), 123, 'milliseconds with SSSS'); + }); + + test('string with format no separators', function (assert) { + moment.locale('en'); + var a = [ + ['MMDDYYYY', '12021999'], + ['DDMMYYYY', '12021999'], + ['YYYYMMDD', '19991202'], + ['DDMMMYYYY', '10Sep2001'] + ], i; + + for (i = 0; i < a.length; i++) { + assert.equal(moment(a[i][1], a[i][0]).format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]); + } + }); + + test('string with format (timezone)', function (assert) { + assert.equal(moment('5 -0700', 'H ZZ').toDate().getUTCHours(), 12, 'parse hours \'5 -0700\' ---> \'H ZZ\''); + assert.equal(moment('5 -07:00', 'H Z').toDate().getUTCHours(), 12, 'parse hours \'5 -07:00\' ---> \'H Z\''); + assert.equal(moment('5 -0730', 'H ZZ').toDate().getUTCMinutes(), 30, 'parse hours \'5 -0730\' ---> \'H ZZ\''); + assert.equal(moment('5 -07:30', 'H Z').toDate().getUTCMinutes(), 30, 'parse hours \'5 -07:0\' ---> \'H Z\''); + assert.equal(moment('5 +0100', 'H ZZ').toDate().getUTCHours(), 4, 'parse hours \'5 +0100\' ---> \'H ZZ\''); + assert.equal(moment('5 +01:00', 'H Z').toDate().getUTCHours(), 4, 'parse hours \'5 +01:00\' ---> \'H Z\''); + assert.equal(moment('5 +0130', 'H ZZ').toDate().getUTCMinutes(), 30, 'parse hours \'5 +0130\' ---> \'H ZZ\''); + assert.equal(moment('5 +01:30', 'H Z').toDate().getUTCMinutes(), 30, 'parse hours \'5 +01:30\' ---> \'H Z\''); + }); + + test('string with format (timezone offset)', function (assert) { + var a, b, c, d, e, f; + a = new Date(Date.UTC(2011, 0, 1, 1)); + b = moment('2011 1 1 0 -01:00', 'YYYY MM DD HH Z'); + assert.equal(a.getHours(), b.hours(), 'date created with utc == parsed string with timezone offset'); + assert.equal(+a, +b, 'date created with utc == parsed string with timezone offset'); + c = moment('2011 2 1 10 -05:00', 'YYYY MM DD HH Z'); + d = moment('2011 2 1 8 -07:00', 'YYYY MM DD HH Z'); + assert.equal(c.hours(), d.hours(), '10 am central time == 8 am pacific time'); + e = moment.utc('Fri, 20 Jul 2012 17:15:00', 'ddd, DD MMM YYYY HH:mm:ss'); + f = moment.utc('Fri, 20 Jul 2012 10:15:00 -0700', 'ddd, DD MMM YYYY HH:mm:ss ZZ'); + assert.equal(e.hours(), f.hours(), 'parse timezone offset in utc'); + }); + + test('string with timezone around start of year', function (assert) { + assert.equal(moment('2000-01-01T00:00:00.000+01:00').toISOString(), '1999-12-31T23:00:00.000Z', '+1:00 around 2000'); + assert.equal(moment('2000-01-01T00:00:00.000-01:00').toISOString(), '2000-01-01T01:00:00.000Z', '-1:00 around 2000'); + assert.equal(moment('1970-01-01T00:00:00.000+01:00').toISOString(), '1969-12-31T23:00:00.000Z', '+1:00 around 1970'); + assert.equal(moment('1970-01-01T00:00:00.000-01:00').toISOString(), '1970-01-01T01:00:00.000Z', '-1:00 around 1970'); + assert.equal(moment('1200-01-01T00:00:00.000+01:00').toISOString(), '1199-12-31T23:00:00.000Z', '+1:00 around 1200'); + assert.equal(moment('1200-01-01T00:00:00.000-01:00').toISOString(), '1200-01-01T01:00:00.000Z', '-1:00 around 1200'); + }); + + test('string with array of formats', function (assert) { + assert.equal(moment('11-02-1999', ['MM-DD-YYYY', 'DD-MM-YYYY']).format('MM DD YYYY'), '11 02 1999', 'switching month and day'); + assert.equal(moment('02-11-1999', ['MM/DD/YYYY', 'YYYY MM DD', 'MM-DD-YYYY']).format('MM DD YYYY'), '02 11 1999', 'year last'); + assert.equal(moment('1999-02-11', ['MM/DD/YYYY', 'YYYY MM DD', 'MM-DD-YYYY']).format('MM DD YYYY'), '02 11 1999', 'year first'); + + assert.equal(moment('02-11-1999', ['MM/DD/YYYY', 'YYYY MM DD']).format('MM DD YYYY'), '02 11 1999', 'year last'); + assert.equal(moment('1999-02-11', ['MM/DD/YYYY', 'YYYY MM DD']).format('MM DD YYYY'), '02 11 1999', 'year first'); + assert.equal(moment('02-11-1999', ['YYYY MM DD', 'MM/DD/YYYY']).format('MM DD YYYY'), '02 11 1999', 'year last'); + assert.equal(moment('1999-02-11', ['YYYY MM DD', 'MM/DD/YYYY']).format('MM DD YYYY'), '02 11 1999', 'year first'); + + assert.equal(moment('13-11-1999', ['MM/DD/YYYY', 'DD/MM/YYYY']).format('MM DD YYYY'), '11 13 1999', 'second must be month'); + assert.equal(moment('11-13-1999', ['MM/DD/YYYY', 'DD/MM/YYYY']).format('MM DD YYYY'), '11 13 1999', 'first must be month'); + assert.equal(moment('01-02-2000', ['MM/DD/YYYY', 'DD/MM/YYYY']).format('MM DD YYYY'), '01 02 2000', 'either can be a month, month first format'); + assert.equal(moment('02-01-2000', ['DD/MM/YYYY', 'MM/DD/YYYY']).format('MM DD YYYY'), '01 02 2000', 'either can be a month, day first format'); + + assert.equal(moment('11-02-10', ['MM/DD/YY', 'YY MM DD', 'DD-MM-YY']).format('MM DD YYYY'), '02 11 2010', 'all unparsed substrings have influence on format penalty'); + assert.equal(moment('11-02-10', ['MM-DD-YY HH:mm', 'YY MM DD']).format('MM DD YYYY'), '02 10 2011', 'prefer formats without extra tokens'); + assert.equal(moment('11-02-10 junk', ['MM-DD-YY', 'YY.MM.DD junk']).format('MM DD YYYY'), '02 10 2011', 'prefer formats that dont result in extra characters'); + assert.equal(moment('11-22-10', ['YY-MM-DD', 'YY-DD-MM']).format('MM DD YYYY'), '10 22 2011', 'prefer valid results'); + + assert.equal(moment('gibberish', ['YY-MM-DD', 'YY-DD-MM']).format('MM DD YYYY'), 'Invalid date', 'doest throw for invalid strings'); + assert.equal(moment('gibberish', []).format('MM DD YYYY'), 'Invalid date', 'doest throw for an empty array'); + + //https://github.com/moment/moment/issues/1143 + assert.equal(moment( + 'System Administrator and Database Assistant (7/1/2011), System Administrator and Database Assistant (7/1/2011), Database Coordinator (7/1/2011), Vice President (7/1/2011), System Administrator and Database Assistant (5/31/2012), Database Coordinator (7/1/2012), System Administrator and Database Assistant (7/1/2013)', + ['MM/DD/YYYY', 'MM-DD-YYYY', 'YYYY-MM-DD', 'YYYY-MM-DDTHH:mm:ssZ']) + .format('YYYY-MM-DD'), '2011-07-01', 'Works for long strings'); + + assert.equal(moment('11-02-10', ['MM.DD.YY', 'DD-MM-YY']).format('MM DD YYYY'), '02 11 2010', 'escape RegExp special characters on comparing'); + + assert.equal(moment('13-10-98', ['DD MM YY', 'DD MM YYYY'])._f, 'DD MM YY', 'use two digit year'); + assert.equal(moment('13-10-1998', ['DD MM YY', 'DD MM YYYY'])._f, 'DD MM YYYY', 'use four digit year'); + + assert.equal(moment('01', ['MM', 'DD'])._f, 'MM', 'Should use first valid format'); + }); + + test('string with array of formats + ISO', function (assert) { + assert.equal(moment('1994', [moment.ISO_8601, 'MM', 'HH:mm', 'YYYY']).year(), 1994, 'iso: assert parse YYYY'); + assert.equal(moment('17:15', [moment.ISO_8601, 'MM', 'HH:mm', 'YYYY']).hour(), 17, 'iso: assert parse HH:mm (1)'); + assert.equal(moment('17:15', [moment.ISO_8601, 'MM', 'HH:mm', 'YYYY']).minutes(), 15, 'iso: assert parse HH:mm (2)'); + assert.equal(moment('06', [moment.ISO_8601, 'MM', 'HH:mm', 'YYYY']).month(), 6 - 1, 'iso: assert parse MM'); + assert.equal(moment('2012-06-01', [moment.ISO_8601, 'MM', 'HH:mm', 'YYYY']).parsingFlags().iso, true, 'iso: assert parse iso'); + assert.equal(moment('2014-05-05', [moment.ISO_8601, 'YYYY-MM-DD']).parsingFlags().iso, true, 'iso: edge case array precedence iso'); + assert.equal(moment('2014-05-05', ['YYYY-MM-DD', moment.ISO_8601]).parsingFlags().iso, false, 'iso: edge case array precedence not iso'); + }); + + test('string with format - years', function (assert) { + assert.equal(moment('67', 'YY').format('YYYY'), '2067', '67 > 2067'); + assert.equal(moment('68', 'YY').format('YYYY'), '2068', '68 > 2068'); + assert.equal(moment('69', 'YY').format('YYYY'), '1969', '69 > 1969'); + assert.equal(moment('70', 'YY').format('YYYY'), '1970', '70 > 1970'); + }); + + test('implicit cloning', function (assert) { + var momentA = moment([2011, 10, 10]), + momentB = moment(momentA); + momentA.month(5); + assert.equal(momentB.month(), 10, 'Calling moment() on a moment will create a clone'); + assert.equal(momentA.month(), 5, 'Calling moment() on a moment will create a clone'); + }); + + test('explicit cloning', function (assert) { + var momentA = moment([2011, 10, 10]), + momentB = momentA.clone(); + momentA.month(5); + assert.equal(momentB.month(), 10, 'Calling moment() on a moment will create a clone'); + assert.equal(momentA.month(), 5, 'Calling moment() on a moment will create a clone'); + }); + + test('cloning carrying over utc mode', function (assert) { + assert.equal(moment().local().clone()._isUTC, false, 'An explicit cloned local moment should have _isUTC == false'); + assert.equal(moment().utc().clone()._isUTC, true, 'An cloned utc moment should have _isUTC == true'); + assert.equal(moment().clone()._isUTC, false, 'An explicit cloned local moment should have _isUTC == false'); + assert.equal(moment.utc().clone()._isUTC, true, 'An explicit cloned utc moment should have _isUTC == true'); + assert.equal(moment(moment().local())._isUTC, false, 'An implicit cloned local moment should have _isUTC == false'); + assert.equal(moment(moment().utc())._isUTC, true, 'An implicit cloned utc moment should have _isUTC == true'); + assert.equal(moment(moment())._isUTC, false, 'An implicit cloned local moment should have _isUTC == false'); + assert.equal(moment(moment.utc())._isUTC, true, 'An implicit cloned utc moment should have _isUTC == true'); + }); + + test('parsing iso', function (assert) { + var offset = moment([2011, 9, 8]).utcOffset(), + pad = function (input) { + if (input < 10) { + return '0' + input; + } + return '' + input; + }, + hourOffset = (offset > 0 ? Math.floor(offset / 60) : Math.ceil(offset / 60)), + minOffset = offset - (hourOffset * 60), + tz = (offset >= 0) ? + '+' + pad(hourOffset) + ':' + pad(minOffset) : + '-' + pad(-hourOffset) + ':' + pad(-minOffset), + tz2 = tz.replace(':', ''), + tz3 = tz2.slice(0, 3), + 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' + tz3, '2011-10-08T18:04:00.000' + tz], + ['2011-10-08T18:04:20' + tz3, '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' + tz3, '2011-10-08T18:04:00.000' + tz], + ['2011-10-08 18:04:20' + tz3, '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], + ['2011-W40', '2011-10-03T00:00:00.000' + tz], + ['2011-W40-6', '2011-10-08T00:00:00.000' + tz], + ['2011-W40-6T18', '2011-10-08T18:00:00.000' + tz], + ['2011-W40-6T18:04', '2011-10-08T18:04:00.000' + tz], + ['2011-W40-6T18:04:20', '2011-10-08T18:04:20.000' + tz], + ['2011-W40-6T18:04' + tz, '2011-10-08T18:04:00.000' + tz], + ['2011-W40-6T18:04:20' + tz, '2011-10-08T18:04:20.000' + tz], + ['2011-W40-6T18:04' + tz2, '2011-10-08T18:04:00.000' + tz], + ['2011-W40-6T18:04:20' + tz2, '2011-10-08T18:04:20.000' + tz], + ['2011-W40-6T18:04' + tz3, '2011-10-08T18:04:00.000' + tz], + ['2011-W40-6T18:04:20' + tz3, '2011-10-08T18:04:20.000' + tz], + ['2011-W40-6T18:04:20.1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['2011-W40-6T18:04:20.11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['2011-W40-6T18:04:20.111' + tz2, '2011-10-08T18:04:20.111' + tz], + ['2011-W40-6 18', '2011-10-08T18:00:00.000' + tz], + ['2011-W40-6 18:04', '2011-10-08T18:04:00.000' + tz], + ['2011-W40-6 18:04:20', '2011-10-08T18:04:20.000' + tz], + ['2011-W40-6 18:04' + tz, '2011-10-08T18:04:00.000' + tz], + ['2011-W40-6 18:04:20' + tz, '2011-10-08T18:04:20.000' + tz], + ['2011-W40-6 18:04' + tz2, '2011-10-08T18:04:00.000' + tz], + ['2011-W40-6 18:04:20' + tz2, '2011-10-08T18:04:20.000' + tz], + ['2011-W40-6 18:04' + tz3, '2011-10-08T18:04:00.000' + tz], + ['2011-W40-6 18:04:20' + tz3, '2011-10-08T18:04:20.000' + tz], + ['2011-W40-6 18:04:20.1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['2011-W40-6 18:04:20.11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['2011-W40-6 18:04:20.111' + tz2, '2011-10-08T18:04:20.111' + tz], + ['2011-281', '2011-10-08T00:00:00.000' + tz], + ['2011-281T18', '2011-10-08T18:00:00.000' + tz], + ['2011-281T18:04', '2011-10-08T18:04:00.000' + tz], + ['2011-281T18:04:20', '2011-10-08T18:04:20.000' + tz], + ['2011-281T18:04' + tz, '2011-10-08T18:04:00.000' + tz], + ['2011-281T18:04:20' + tz, '2011-10-08T18:04:20.000' + tz], + ['2011-281T18:04' + tz2, '2011-10-08T18:04:00.000' + tz], + ['2011-281T18:04:20' + tz2, '2011-10-08T18:04:20.000' + tz], + ['2011-281T18:04' + tz3, '2011-10-08T18:04:00.000' + tz], + ['2011-281T18:04:20' + tz3, '2011-10-08T18:04:20.000' + tz], + ['2011-281T18:04:20.1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['2011-281T18:04:20.11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['2011-281T18:04:20.111' + tz2, '2011-10-08T18:04:20.111' + tz], + ['2011-281 18', '2011-10-08T18:00:00.000' + tz], + ['2011-281 18:04', '2011-10-08T18:04:00.000' + tz], + ['2011-281 18:04:20', '2011-10-08T18:04:20.000' + tz], + ['2011-281 18:04' + tz, '2011-10-08T18:04:00.000' + tz], + ['2011-281 18:04:20' + tz, '2011-10-08T18:04:20.000' + tz], + ['2011-281 18:04' + tz2, '2011-10-08T18:04:00.000' + tz], + ['2011-281 18:04:20' + tz2, '2011-10-08T18:04:20.000' + tz], + ['2011-281 18:04' + tz3, '2011-10-08T18:04:00.000' + tz], + ['2011-281 18:04:20' + tz3, '2011-10-08T18:04:20.000' + tz], + ['2011-281 18:04:20.1' + tz2, '2011-10-08T18:04:20.100' + tz], + ['2011-281 18:04:20.11' + tz2, '2011-10-08T18:04:20.110' + tz], + ['2011-281 18:04:20.111' + tz2, '2011-10-08T18:04:20.111' + tz] + ], i; + for (i = 0; i < formats.length; i++) { + assert.equal(moment(formats[i][0]).format('YYYY-MM-DDTHH:mm:ss.SSSZ'), formats[i][1], 'moment should be able to parse ISO ' + formats[i][0]); + } + }); + + test('parsing iso week year/week/weekday', function (assert) { + assert.equal(moment.utc('2007-W01').format(), '2007-01-01T00:00:00+00:00', '2008 week 1 (1st Jan Mon)'); + assert.equal(moment.utc('2008-W01').format(), '2007-12-31T00:00:00+00:00', '2008 week 1 (1st Jan Tue)'); + assert.equal(moment.utc('2003-W01').format(), '2002-12-30T00:00:00+00:00', '2008 week 1 (1st Jan Wed)'); + assert.equal(moment.utc('2009-W01').format(), '2008-12-29T00:00:00+00:00', '2009 week 1 (1st Jan Thu)'); + assert.equal(moment.utc('2010-W01').format(), '2010-01-04T00:00:00+00:00', '2010 week 1 (1st Jan Fri)'); + assert.equal(moment.utc('2011-W01').format(), '2011-01-03T00:00:00+00:00', '2011 week 1 (1st Jan Sat)'); + assert.equal(moment.utc('2012-W01').format(), '2012-01-02T00:00:00+00:00', '2012 week 1 (1st Jan Sun)'); + }); + + test('parsing week year/week/weekday (dow 1, doy 4)', function (assert) { + moment.locale('dow:1,doy:4', {week: {dow: 1, doy: 4}}); + + assert.equal(moment.utc('2007-01', 'gggg-ww').format(), '2007-01-01T00:00:00+00:00', '2007 week 1 (1st Jan Mon)'); + assert.equal(moment.utc('2008-01', 'gggg-ww').format(), '2007-12-31T00:00:00+00:00', '2008 week 1 (1st Jan Tue)'); + assert.equal(moment.utc('2003-01', 'gggg-ww').format(), '2002-12-30T00:00:00+00:00', '2003 week 1 (1st Jan Wed)'); + assert.equal(moment.utc('2009-01', 'gggg-ww').format(), '2008-12-29T00:00:00+00:00', '2009 week 1 (1st Jan Thu)'); + assert.equal(moment.utc('2010-01', 'gggg-ww').format(), '2010-01-04T00:00:00+00:00', '2010 week 1 (1st Jan Fri)'); + assert.equal(moment.utc('2011-01', 'gggg-ww').format(), '2011-01-03T00:00:00+00:00', '2011 week 1 (1st Jan Sat)'); + assert.equal(moment.utc('2012-01', 'gggg-ww').format(), '2012-01-02T00:00:00+00:00', '2012 week 1 (1st Jan Sun)'); + + moment.defineLocale('dow:1,doy:4', null); + }); + + test('parsing week year/week/weekday (dow 1, doy 7)', function (assert) { + moment.locale('dow:1,doy:7', {week: {dow: 1, doy: 7}}); + + assert.equal(moment.utc('2007-01', 'gggg-ww').format(), '2007-01-01T00:00:00+00:00', '2007 week 1 (1st Jan Mon)'); + assert.equal(moment.utc('2008-01', 'gggg-ww').format(), '2007-12-31T00:00:00+00:00', '2008 week 1 (1st Jan Tue)'); + assert.equal(moment.utc('2003-01', 'gggg-ww').format(), '2002-12-30T00:00:00+00:00', '2003 week 1 (1st Jan Wed)'); + assert.equal(moment.utc('2009-01', 'gggg-ww').format(), '2008-12-29T00:00:00+00:00', '2009 week 1 (1st Jan Thu)'); + assert.equal(moment.utc('2010-01', 'gggg-ww').format(), '2009-12-28T00:00:00+00:00', '2010 week 1 (1st Jan Fri)'); + assert.equal(moment.utc('2011-01', 'gggg-ww').format(), '2010-12-27T00:00:00+00:00', '2011 week 1 (1st Jan Sat)'); + assert.equal(moment.utc('2012-01', 'gggg-ww').format(), '2011-12-26T00:00:00+00:00', '2012 week 1 (1st Jan Sun)'); + moment.defineLocale('dow:1,doy:7', null); + }); + + test('parsing week year/week/weekday (dow 0, doy 6)', function (assert) { + moment.locale('dow:0,doy:6', {week: {dow: 0, doy: 6}}); + + assert.equal(moment.utc('2007-01', 'gggg-ww').format(), '2006-12-31T00:00:00+00:00', '2007 week 1 (1st Jan Mon)'); + assert.equal(moment.utc('2008-01', 'gggg-ww').format(), '2007-12-30T00:00:00+00:00', '2008 week 1 (1st Jan Tue)'); + assert.equal(moment.utc('2003-01', 'gggg-ww').format(), '2002-12-29T00:00:00+00:00', '2003 week 1 (1st Jan Wed)'); + assert.equal(moment.utc('2009-01', 'gggg-ww').format(), '2008-12-28T00:00:00+00:00', '2009 week 1 (1st Jan Thu)'); + assert.equal(moment.utc('2010-01', 'gggg-ww').format(), '2009-12-27T00:00:00+00:00', '2010 week 1 (1st Jan Fri)'); + assert.equal(moment.utc('2011-01', 'gggg-ww').format(), '2010-12-26T00:00:00+00:00', '2011 week 1 (1st Jan Sat)'); + assert.equal(moment.utc('2012-01', 'gggg-ww').format(), '2012-01-01T00:00:00+00:00', '2012 week 1 (1st Jan Sun)'); + moment.defineLocale('dow:0,doy:6', null); + }); + + test('parsing week year/week/weekday (dow 6, doy 12)', function (assert) { + moment.locale('dow:6,doy:12', {week: {dow: 6, doy: 12}}); + + assert.equal(moment.utc('2007-01', 'gggg-ww').format(), '2006-12-30T00:00:00+00:00', '2007 week 1 (1st Jan Mon)'); + assert.equal(moment.utc('2008-01', 'gggg-ww').format(), '2007-12-29T00:00:00+00:00', '2008 week 1 (1st Jan Tue)'); + assert.equal(moment.utc('2003-01', 'gggg-ww').format(), '2002-12-28T00:00:00+00:00', '2003 week 1 (1st Jan Wed)'); + assert.equal(moment.utc('2009-01', 'gggg-ww').format(), '2008-12-27T00:00:00+00:00', '2009 week 1 (1st Jan Thu)'); + assert.equal(moment.utc('2010-01', 'gggg-ww').format(), '2009-12-26T00:00:00+00:00', '2010 week 1 (1st Jan Fri)'); + assert.equal(moment.utc('2011-01', 'gggg-ww').format(), '2011-01-01T00:00:00+00:00', '2011 week 1 (1st Jan Sat)'); + assert.equal(moment.utc('2012-01', 'gggg-ww').format(), '2011-12-31T00:00:00+00:00', '2012 week 1 (1st Jan Sun)'); + }); + + test('parsing ISO with Z', function (assert) { + var i, mom, formats = [ + ['2011-10-08T18:04', '2011-10-08T18:04:00.000'], + ['2011-10-08T18:04:20', '2011-10-08T18:04:20.000'], + ['2011-10-08T18:04:20.1', '2011-10-08T18:04:20.100'], + ['2011-10-08T18:04:20.11', '2011-10-08T18:04:20.110'], + ['2011-10-08T18:04:20.111', '2011-10-08T18:04:20.111'], + ['2011-W40-6T18', '2011-10-08T18:00:00.000'], + ['2011-W40-6T18:04', '2011-10-08T18:04:00.000'], + ['2011-W40-6T18:04:20', '2011-10-08T18:04:20.000'], + ['2011-W40-6T18:04:20.1', '2011-10-08T18:04:20.100'], + ['2011-W40-6T18:04:20.11', '2011-10-08T18:04:20.110'], + ['2011-W40-6T18:04:20.111', '2011-10-08T18:04:20.111'], + ['2011-281T18', '2011-10-08T18:00:00.000'], + ['2011-281T18:04', '2011-10-08T18:04:00.000'], + ['2011-281T18:04:20', '2011-10-08T18:04:20.000'], + ['2011-281T18:04:20', '2011-10-08T18:04:20.000'], + ['2011-281T18:04:20.1', '2011-10-08T18:04:20.100'], + ['2011-281T18:04:20.11', '2011-10-08T18:04:20.110'], + ['2011-281T18:04:20.111', '2011-10-08T18:04:20.111'] + ]; + + for (i = 0; i < formats.length; i++) { + mom = moment(formats[i][0] + 'Z').utc(); + assert.equal(mom.format('YYYY-MM-DDTHH:mm:ss.SSS'), formats[i][1], 'moment should be able to parse ISO in UTC ' + formats[i][0] + 'Z'); + + mom = moment(formats[i][0] + ' Z').utc(); + assert.equal(mom.format('YYYY-MM-DDTHH:mm:ss.SSS'), formats[i][1], 'moment should be able to parse ISO in UTC ' + formats[i][0] + ' Z'); + } + }); + + test('parsing iso with T', function (assert) { + assert.equal(moment('2011-10-08T18')._f, 'YYYY-MM-DDTHH', 'should include \'T\' in the format'); + assert.equal(moment('2011-10-08T18:20')._f, 'YYYY-MM-DDTHH:mm', 'should include \'T\' in the format'); + assert.equal(moment('2011-10-08T18:20:13')._f, 'YYYY-MM-DDTHH:mm:ss', 'should include \'T\' in the format'); + assert.equal(moment('2011-10-08T18:20:13.321')._f, 'YYYY-MM-DDTHH:mm:ss.SSSS', 'should include \'T\' in the format'); + + assert.equal(moment('2011-10-08 18')._f, 'YYYY-MM-DD HH', 'should not include \'T\' in the format'); + assert.equal(moment('2011-10-08 18:20')._f, 'YYYY-MM-DD HH:mm', 'should not include \'T\' in the format'); + assert.equal(moment('2011-10-08 18:20:13')._f, 'YYYY-MM-DD HH:mm:ss', 'should not include \'T\' in the format'); + assert.equal(moment('2011-10-08 18:20:13.321')._f, 'YYYY-MM-DD HH:mm:ss.SSSS', 'should not include \'T\' in the format'); + }); + + test('parsing iso Z timezone', function (assert) { + 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'] + ]; + for (i = 0; i < formats.length; i++) { + assert.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('parsing iso Z timezone into local', function (assert) { + var m = moment('2011-10-08T18:04:20.111Z'); + + assert.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('parsing iso with more subsecond precision digits', function (assert) { + assert.equal(moment.utc('2013-07-31T22:00:00.0000000Z').format(), '2013-07-31T22:00:00+00:00', 'more than 3 subsecond digits'); + }); + + test('null or empty', function (assert) { + assert.equal(moment('').isValid(), false, 'moment(\'\') is not valid'); + assert.equal(moment(null).isValid(), false, 'moment(null) is not valid'); + assert.equal(moment(null, 'YYYY-MM-DD').isValid(), false, 'moment(\'\', \'format\') is not valid'); + assert.equal(moment('', 'YYYY-MM-DD').isValid(), false, 'moment(\'\', \'format\') is not valid'); + assert.equal(moment.utc('').isValid(), false, 'moment.utc(\'\') is not valid'); + assert.equal(moment.utc(null).isValid(), false, 'moment.utc(null) is not valid'); + assert.equal(moment.utc(null, 'YYYY-MM-DD').isValid(), false, 'moment.utc(null) is not valid'); + assert.equal(moment.utc('', 'YYYY-MM-DD').isValid(), false, 'moment.utc(\'\', \'YYYY-MM-DD\') is not valid'); + }); + + test('first century', function (assert) { + assert.equal(moment([0, 0, 1]).format('YYYY-MM-DD'), '0000-01-01', 'Year AD 0'); + assert.equal(moment([99, 0, 1]).format('YYYY-MM-DD'), '0099-01-01', 'Year AD 99'); + assert.equal(moment([999, 0, 1]).format('YYYY-MM-DD'), '0999-01-01', 'Year AD 999'); + assert.equal(moment('0 1 1', 'YYYY MM DD').format('YYYY-MM-DD'), '0000-01-01', 'Year AD 0'); + assert.equal(moment('99 1 1', 'YYYY MM DD').format('YYYY-MM-DD'), '0099-01-01', 'Year AD 99'); + assert.equal(moment('999 1 1', 'YYYY MM DD').format('YYYY-MM-DD'), '0999-01-01', 'Year AD 999'); + assert.equal(moment('0 1 1', 'YYYYY MM DD').format('YYYYY-MM-DD'), '00000-01-01', 'Year AD 0'); + assert.equal(moment('99 1 1', 'YYYYY MM DD').format('YYYYY-MM-DD'), '00099-01-01', 'Year AD 99'); + assert.equal(moment('999 1 1', 'YYYYY MM DD').format('YYYYY-MM-DD'), '00999-01-01', 'Year AD 999'); + }); + + test('six digit years', function (assert) { + assert.equal(moment([-270000, 0, 1]).format('YYYYY-MM-DD'), '-270000-01-01', 'format BC 270,001'); + assert.equal(moment([270000, 0, 1]).format('YYYYY-MM-DD'), '270000-01-01', 'format AD 270,000'); + assert.equal(moment('-270000-01-01', 'YYYYY-MM-DD').toDate().getFullYear(), -270000, 'parse BC 270,001'); + assert.equal(moment('270000-01-01', 'YYYYY-MM-DD').toDate().getFullYear(), 270000, 'parse AD 270,000'); + assert.equal(moment('+270000-01-01', 'YYYYY-MM-DD').toDate().getFullYear(), 270000, 'parse AD +270,000'); + assert.equal(moment.utc('-270000-01-01', 'YYYYY-MM-DD').toDate().getUTCFullYear(), -270000, 'parse utc BC 270,001'); + assert.equal(moment.utc('270000-01-01', 'YYYYY-MM-DD').toDate().getUTCFullYear(), 270000, 'parse utc AD 270,000'); + assert.equal(moment.utc('+270000-01-01', 'YYYYY-MM-DD').toDate().getUTCFullYear(), 270000, 'parse utc AD +270,000'); + }); + + test('negative four digit years', function (assert) { + assert.equal(moment('-1000-01-01', 'YYYYY-MM-DD').toDate().getFullYear(), -1000, 'parse BC 1,001'); + assert.equal(moment.utc('-1000-01-01', 'YYYYY-MM-DD').toDate().getUTCFullYear(), -1000, 'parse utc BC 1,001'); + }); + + test('strict parsing', function (assert) { + assert.equal(moment('2014-', 'YYYY-Q', true).isValid(), false, 'fail missing quarter'); + + assert.equal(moment('2012-05', 'YYYY-MM', true).format('YYYY-MM'), '2012-05', 'parse correct string'); + assert.equal(moment(' 2012-05', 'YYYY-MM', true).isValid(), false, 'fail on extra whitespace'); + assert.equal(moment('foo 2012-05', '[foo] YYYY-MM', true).format('YYYY-MM'), '2012-05', 'handle fixed text'); + assert.equal(moment('2012 05', 'YYYY-MM', true).isValid(), false, 'fail on different separator'); + assert.equal(moment('2012 05', 'YYYY MM DD', true).isValid(), false, 'fail on too many tokens'); + + assert.equal(moment('05 30 2010', ['DD MM YYYY', 'MM DD YYYY'], true).format('MM DD YYYY'), '05 30 2010', 'array with bad date'); + assert.equal(moment('05 30 2010', ['', 'MM DD YYYY'], true).format('MM DD YYYY'), '05 30 2010', 'array with invalid format'); + assert.equal(moment('05 30 2010', [' DD MM YYYY', 'MM DD YYYY'], true).format('MM DD YYYY'), '05 30 2010', 'array with non-matching format'); + + assert.equal(moment('2010.*...', 'YYYY.*', true).isValid(), false, 'invalid format with regex chars'); + assert.equal(moment('2010.*', 'YYYY.*', true).year(), 2010, 'valid format with regex chars'); + assert.equal(moment('.*2010.*', '.*YYYY.*', true).year(), 2010, 'valid format with regex chars on both sides'); + + //strict tokens + assert.equal(moment('-5-05-25', 'YYYY-MM-DD', true).isValid(), false, 'invalid negative year'); + assert.equal(moment('2-05-25', 'YYYY-MM-DD', true).isValid(), false, 'invalid one-digit year'); + assert.equal(moment('20-05-25', 'YYYY-MM-DD', true).isValid(), false, 'invalid two-digit year'); + assert.equal(moment('201-05-25', 'YYYY-MM-DD', true).isValid(), false, 'invalid three-digit year'); + assert.equal(moment('2010-05-25', 'YYYY-MM-DD', true).isValid(), true, 'valid four-digit year'); + assert.equal(moment('22010-05-25', 'YYYY-MM-DD', true).isValid(), false, 'invalid five-digit year'); + + assert.equal(moment('12-05-25', 'YY-MM-DD', true).isValid(), true, 'valid two-digit year'); + assert.equal(moment('2012-05-25', 'YY-MM-DD', true).isValid(), false, 'invalid four-digit year'); + + assert.equal(moment('-5-05-25', 'Y-MM-DD', true).isValid(), true, 'valid negative year'); + assert.equal(moment('2-05-25', 'Y-MM-DD', true).isValid(), true, 'valid one-digit year'); + assert.equal(moment('20-05-25', 'Y-MM-DD', true).isValid(), true, 'valid two-digit year'); + assert.equal(moment('201-05-25', 'Y-MM-DD', true).isValid(), true, 'valid three-digit year'); + + assert.equal(moment('2012-5-25', 'YYYY-M-DD', true).isValid(), true, 'valid one-digit month'); + assert.equal(moment('2012-5-25', 'YYYY-MM-DD', true).isValid(), false, 'invalid one-digit month'); + assert.equal(moment('2012-05-25', 'YYYY-M-DD', true).isValid(), true, 'valid one-digit month'); + assert.equal(moment('2012-05-25', 'YYYY-MM-DD', true).isValid(), true, 'valid one-digit month'); + + assert.equal(moment('2012-05-2', 'YYYY-MM-D', true).isValid(), true, 'valid one-digit day'); + assert.equal(moment('2012-05-2', 'YYYY-MM-DD', true).isValid(), false, 'invalid one-digit day'); + assert.equal(moment('2012-05-02', 'YYYY-MM-D', true).isValid(), true, 'valid two-digit day'); + assert.equal(moment('2012-05-02', 'YYYY-MM-DD', true).isValid(), true, 'valid two-digit day'); + + assert.equal(moment('+002012-05-25', 'YYYYY-MM-DD', true).isValid(), true, 'valid six-digit year'); + assert.equal(moment('+2012-05-25', 'YYYYY-MM-DD', true).isValid(), false, 'invalid four-digit year'); + + //thse are kinda pointless, but they should work as expected + assert.equal(moment('1', 'S', true).isValid(), true, 'valid one-digit milisecond'); + assert.equal(moment('12', 'S', true).isValid(), false, 'invalid two-digit milisecond'); + assert.equal(moment('123', 'S', true).isValid(), false, 'invalid three-digit milisecond'); + + assert.equal(moment('1', 'SS', true).isValid(), false, 'invalid one-digit milisecond'); + assert.equal(moment('12', 'SS', true).isValid(), true, 'valid two-digit milisecond'); + assert.equal(moment('123', 'SS', true).isValid(), false, 'invalid three-digit milisecond'); + + assert.equal(moment('1', 'SSS', true).isValid(), false, 'invalid one-digit milisecond'); + assert.equal(moment('12', 'SSS', true).isValid(), false, 'invalid two-digit milisecond'); + assert.equal(moment('123', 'SSS', true).isValid(), true, 'valid three-digit milisecond'); + + // strict parsing respects month length + assert.ok(moment('1 January 2000', 'D MMMM YYYY', true).isValid(), 'capital long-month + MMMM'); + assert.ok(!moment('1 January 2000', 'D MMM YYYY', true).isValid(), 'capital long-month + MMM'); + assert.ok(!moment('1 Jan 2000', 'D MMMM YYYY', true).isValid(), 'capital short-month + MMMM'); + assert.ok(moment('1 Jan 2000', 'D MMM YYYY', true).isValid(), 'capital short-month + MMM'); + assert.ok(moment('1 january 2000', 'D MMMM YYYY', true).isValid(), 'lower long-month + MMMM'); + assert.ok(!moment('1 january 2000', 'D MMM YYYY', true).isValid(), 'lower long-month + MMM'); + assert.ok(!moment('1 jan 2000', 'D MMMM YYYY', true).isValid(), 'lower short-month + MMMM'); + assert.ok(moment('1 jan 2000', 'D MMM YYYY', true).isValid(), 'lower short-month + MMM'); + }); + + test('parsing into a locale', function (assert) { + moment.defineLocale('parselocale', { + 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.locale('en'); + + assert.equal(moment('2012 seven', 'YYYY MMM', 'parselocale').month(), 6, 'should be able to parse in a specific locale'); + + moment.locale('parselocale'); + + assert.equal(moment('2012 july', 'YYYY MMM', 'en').month(), 6, 'should be able to parse in a specific locale'); + + moment.defineLocale('parselocale', null); + }); + + function getVerifier(test) { + return function (input, format, expected, description, asymetrical) { + var m = moment(input, format); + test.equal(m.format('YYYY MM DD'), expected, 'compare: ' + description); + + //test round trip + if (!asymetrical) { + test.equal(m.format(format), input, 'round trip: ' + description); + } + }; + } + + test('parsing week and weekday information', function (assert) { + var ver = getVerifier(assert); + + // year + ver('12', 'gg', '2012 01 01', 'week-year two digits'); + ver('2012', 'gggg', '2012 01 01', 'week-year four digits'); + + ver('99', 'gg', '1998 12 27', 'week-year two digits previous year'); + ver('1999', 'gggg', '1998 12 27', 'week-year four digits previous year'); + + ver('99', 'GG', '1999 01 04', 'iso week-year two digits'); + ver('1999', 'GGGG', '1999 01 04', 'iso week-year four digits'); + + ver('13', 'GG', '2012 12 31', 'iso week-year two digits previous year'); + ver('2013', 'GGGG', '2012 12 31', 'iso week-year four digits previous year'); + + // year + week + ver('1999 37', 'gggg w', '1999 09 05', 'week'); + ver('1999 37', 'gggg ww', '1999 09 05', 'week double'); + ver('1999 37', 'GGGG W', '1999 09 13', 'iso week'); + ver('1999 37', 'GGGG WW', '1999 09 13', 'iso week double'); + + ver('1999 37 4', 'GGGG WW E', '1999 09 16', 'iso day'); + ver('1999 37 04', 'GGGG WW E', '1999 09 16', 'iso day wide', true); + + ver('1999 37 4', 'gggg ww e', '1999 09 09', 'day'); + ver('1999 37 04', 'gggg ww e', '1999 09 09', 'day wide', true); + + // year + week + day + ver('1999 37 4', 'gggg ww d', '1999 09 09', 'd'); + ver('1999 37 Th', 'gggg ww dd', '1999 09 09', 'dd'); + ver('1999 37 Thu', 'gggg ww ddd', '1999 09 09', 'ddd'); + ver('1999 37 Thursday', 'gggg ww dddd', '1999 09 09', 'dddd'); + + // lower-order only + assert.equal(moment('22', 'ww').week(), 22, 'week sets the week by itself'); + assert.equal(moment('22', 'ww').weekYear(), moment().weekYear(), 'week keeps this year'); + assert.equal(moment('2012 22', 'YYYY ww').weekYear(), 2012, 'week keeps parsed year'); + + assert.equal(moment('22', 'WW').isoWeek(), 22, 'iso week sets the week by itself'); + assert.equal(moment('2012 22', 'YYYY WW').weekYear(), 2012, 'iso week keeps parsed year'); + assert.equal(moment('22', 'WW').isoWeekYear(), moment().isoWeekYear(), 'iso week keeps this year'); + + // order + ver('6 2013 2', 'e gggg w', '2013 01 12', 'order doesn\'t matter'); + ver('6 2013 2', 'E GGGG W', '2013 01 12', 'iso order doesn\'t matter'); + + //can parse other stuff too + assert.equal(moment('1999-W37-4 3:30', 'GGGG-[W]WW-E HH:mm').format('YYYY MM DD HH:mm'), '1999 09 16 03:30', 'parsing weeks and hours'); + + // In safari, all years before 1300 are shifted back with one day. + // http://stackoverflow.com/questions/20768975/safari-subtracts-1-day-from-dates-before-1300 + if (new Date('1300-01-01').getUTCFullYear() === 1300) { + // Years less than 100 + ver('0098-06', 'GGGG-WW', '0098 02 03', 'small years work', true); + } + }); + + test('parsing localized weekdays', function (assert) { + var ver = getVerifier(assert); + try { + moment.locale('dow:1,doy:4', { + 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('_'), + week: {dow: 1, doy: 4} + }); + ver('1999 37 4', 'GGGG WW E', '1999 09 16', 'iso ignores locale'); + ver('1999 37 7', 'GGGG WW E', '1999 09 19', 'iso ignores locale'); + + ver('1999 37 0', 'gggg ww e', '1999 09 13', 'localized e uses local doy and dow: 0 = monday'); + ver('1999 37 4', 'gggg ww e', '1999 09 17', 'localized e uses local doy and dow: 4 = friday'); + + ver('1999 37 1', 'gggg ww d', '1999 09 13', 'localized d uses 0-indexed days: 1 = monday'); + ver('1999 37 Lu', 'gggg ww dd', '1999 09 13', 'localized d uses 0-indexed days: Mo'); + ver('1999 37 lun.', 'gggg ww ddd', '1999 09 13', 'localized d uses 0-indexed days: Mon'); + ver('1999 37 lundi', 'gggg ww dddd', '1999 09 13', 'localized d uses 0-indexed days: Monday'); + ver('1999 37 4', 'gggg ww d', '1999 09 16', 'localized d uses 0-indexed days: 4'); + + //sunday goes at the end of the week + ver('1999 37 0', 'gggg ww d', '1999 09 19', 'localized d uses 0-indexed days: 0 = sund'); + ver('1999 37 Di', 'gggg ww dd', '1999 09 19', 'localized d uses 0-indexed days: 0 = sund'); + } + finally { + moment.locale('en'); + } + }); + + test('parsing with customized two-digit year', function (assert) { + var original = moment.parseTwoDigitYear; + try { + assert.equal(moment('68', 'YY').year(), 2068); + assert.equal(moment('69', 'YY').year(), 1969); + moment.parseTwoDigitYear = function (input) { + return +input + (+input > 30 ? 1900 : 2000); + }; + assert.equal(moment('68', 'YY').year(), 1968); + assert.equal(moment('67', 'YY').year(), 1967); + assert.equal(moment('31', 'YY').year(), 1931); + assert.equal(moment('30', 'YY').year(), 2030); + } + finally { + moment.parseTwoDigitYear = original; + } + }); + + test('array with strings', function (assert) { + assert.equal(moment(['2014', '7', '31']).isValid(), true, 'string array + isValid'); + }); + + test('utc with array of formats', function (assert) { + assert.equal(moment.utc('2014-01-01', ['YYYY-MM-DD', 'YYYY-MM']).format(), '2014-01-01T00:00:00+00:00', 'moment.utc works with array of formats'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function each(array, callback) { + var i; + for (i = 0; i < array.length; i++) { + callback(array[i], i, array); + } + } + + var helpers_each = each; + + module('days in month'); + + test('days in month', function (assert) { + helpers_each([31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31], function (days, i) { + var firstDay = moment([2012, i]), + lastDay = moment([2012, i, days]); + assert.equal(firstDay.daysInMonth(), days, firstDay.format('L') + ' should have ' + days + ' days.'); + assert.equal(lastDay.daysInMonth(), days, lastDay.format('L') + ' should have ' + days + ' days.'); + }); + }); + + test('days in month leap years', function (assert) { + assert.equal(moment([2010, 1]).daysInMonth(), 28, 'Feb 2010 should have 28 days'); + assert.equal(moment([2100, 1]).daysInMonth(), 28, 'Feb 2100 should have 28 days'); + assert.equal(moment([2008, 1]).daysInMonth(), 29, 'Feb 2008 should have 29 days'); + assert.equal(moment([2000, 1]).daysInMonth(), 29, 'Feb 2000 should have 29 days'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function equal(assert, a, b, message) { + assert.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.utcOffset() !== current.utcOffset()) { + end = current.clone(); + current = last.clone(); + break; + } + } + + while (current < end) { + last = current.clone(); + current.add(1, 'hour'); + if (last.utcOffset() !== current.utcOffset()) { + return { + moment : last, + diff : -(current.utcOffset() - last.utcOffset()) / 60 + }; + } + } + } + + module('diff'); + + test('diff', function (assert) { + assert.equal(moment(1000).diff(0), 1000, '1 second - 0 = 1000'); + assert.equal(moment(1000).diff(500), 500, '1 second - 0.5 seconds = 500'); + assert.equal(moment(0).diff(1000), -1000, '0 - 1 second = -1000'); + assert.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); + assert.equal(moment(oneHourDate).diff(nowDate), 60 * 60 * 1000, '1 hour from now = 3600000'); + }); + + test('diff key after', function (assert) { + assert.equal(moment([2010]).diff([2011], 'years'), -1, 'year diff'); + assert.equal(moment([2010]).diff([2010, 2], 'months'), -2, 'month diff'); + assert.equal(moment([2010]).diff([2010, 0, 7], 'weeks'), 0, 'week diff'); + assert.equal(moment([2010]).diff([2010, 0, 8], 'weeks'), -1, 'week diff'); + assert.equal(moment([2010]).diff([2010, 0, 21], 'weeks'), -2, 'week diff'); + assert.equal(moment([2010]).diff([2010, 0, 22], 'weeks'), -3, 'week diff'); + assert.equal(moment([2010]).diff([2010, 0, 4], 'days'), -3, 'day diff'); + assert.equal(moment([2010]).diff([2010, 0, 1, 4], 'hours'), -4, 'hour diff'); + assert.equal(moment([2010]).diff([2010, 0, 1, 0, 5], 'minutes'), -5, 'minute diff'); + assert.equal(moment([2010]).diff([2010, 0, 1, 0, 0, 6], 'seconds'), -6, 'second diff'); + }); + + test('diff key before', function (assert) { + assert.equal(moment([2011]).diff([2010], 'years'), 1, 'year diff'); + assert.equal(moment([2010, 2]).diff([2010], 'months'), 2, 'month diff'); + assert.equal(moment([2010, 0, 4]).diff([2010], 'days'), 3, 'day diff'); + assert.equal(moment([2010, 0, 7]).diff([2010], 'weeks'), 0, 'week diff'); + assert.equal(moment([2010, 0, 8]).diff([2010], 'weeks'), 1, 'week diff'); + assert.equal(moment([2010, 0, 21]).diff([2010], 'weeks'), 2, 'week diff'); + assert.equal(moment([2010, 0, 22]).diff([2010], 'weeks'), 3, 'week diff'); + assert.equal(moment([2010, 0, 1, 4]).diff([2010], 'hours'), 4, 'hour diff'); + assert.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'minutes'), 5, 'minute diff'); + assert.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 'seconds'), 6, 'second diff'); + }); + + test('diff key before singular', function (assert) { + assert.equal(moment([2011]).diff([2010], 'year'), 1, 'year diff singular'); + assert.equal(moment([2010, 2]).diff([2010], 'month'), 2, 'month diff singular'); + assert.equal(moment([2010, 0, 4]).diff([2010], 'day'), 3, 'day diff singular'); + assert.equal(moment([2010, 0, 7]).diff([2010], 'week'), 0, 'week diff singular'); + assert.equal(moment([2010, 0, 8]).diff([2010], 'week'), 1, 'week diff singular'); + assert.equal(moment([2010, 0, 21]).diff([2010], 'week'), 2, 'week diff singular'); + assert.equal(moment([2010, 0, 22]).diff([2010], 'week'), 3, 'week diff singular'); + assert.equal(moment([2010, 0, 1, 4]).diff([2010], 'hour'), 4, 'hour diff singular'); + assert.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'minute'), 5, 'minute diff singular'); + assert.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 'second'), 6, 'second diff singular'); + }); + + test('diff key before abbreviated', function (assert) { + assert.equal(moment([2011]).diff([2010], 'y'), 1, 'year diff abbreviated'); + assert.equal(moment([2010, 2]).diff([2010], 'M'), 2, 'month diff abbreviated'); + assert.equal(moment([2010, 0, 4]).diff([2010], 'd'), 3, 'day diff abbreviated'); + assert.equal(moment([2010, 0, 7]).diff([2010], 'w'), 0, 'week diff abbreviated'); + assert.equal(moment([2010, 0, 8]).diff([2010], 'w'), 1, 'week diff abbreviated'); + assert.equal(moment([2010, 0, 21]).diff([2010], 'w'), 2, 'week diff abbreviated'); + assert.equal(moment([2010, 0, 22]).diff([2010], 'w'), 3, 'week diff abbreviated'); + assert.equal(moment([2010, 0, 1, 4]).diff([2010], 'h'), 4, 'hour diff abbreviated'); + assert.equal(moment([2010, 0, 1, 0, 5]).diff([2010], 'm'), 5, 'minute diff abbreviated'); + assert.equal(moment([2010, 0, 1, 0, 0, 6]).diff([2010], 's'), 6, 'second diff abbreviated'); + }); + + test('diff month', function (assert) { + assert.equal(moment([2011, 0, 31]).diff([2011, 2, 1], 'months'), -1, 'month diff'); + }); + + test('diff across DST', function (assert) { + var dst = dstForYear(2012), a, b, daysInMonth; + if (!dst) { + assert.equal(42, 42, 'at least one assertion'); + return; + } + + a = dst.moment; + b = a.clone().utc().add(12, 'hours').local(); + daysInMonth = (a.daysInMonth() + b.daysInMonth()) / 2; + assert.equal(b.diff(a, 'milliseconds', true), 12 * 60 * 60 * 1000, + 'ms diff across DST'); + assert.equal(b.diff(a, 'seconds', true), 12 * 60 * 60, + 'second diff across DST'); + assert.equal(b.diff(a, 'minutes', true), 12 * 60, + 'minute diff across DST'); + assert.equal(b.diff(a, 'hours', true), 12, + 'hour diff across DST'); + assert.equal(b.diff(a, 'days', true), (12 - dst.diff) / 24, + 'day diff across DST'); + equal(assert, b.diff(a, 'weeks', true), (12 - dst.diff) / 24 / 7, + 'week diff across DST'); + assert.ok(0.95 / (2 * 31) < b.diff(a, 'months', true), + 'month diff across DST, lower bound'); + assert.ok(b.diff(a, 'month', true) < 1.05 / (2 * 28), + 'month diff across DST, upper bound'); + assert.ok(0.95 / (2 * 31 * 12) < b.diff(a, 'years', true), + 'year diff across DST, lower bound'); + assert.ok(b.diff(a, 'year', true) < 1.05 / (2 * 28 * 12), + 'year diff across DST, upper bound'); + + a = dst.moment; + b = a.clone().utc().add(12 + dst.diff, 'hours').local(); + daysInMonth = (a.daysInMonth() + b.daysInMonth()) / 2; + + assert.equal(b.diff(a, 'milliseconds', true), + (12 + dst.diff) * 60 * 60 * 1000, + 'ms diff across DST'); + assert.equal(b.diff(a, 'seconds', true), (12 + dst.diff) * 60 * 60, + 'second diff across DST'); + assert.equal(b.diff(a, 'minutes', true), (12 + dst.diff) * 60, + 'minute diff across DST'); + assert.equal(b.diff(a, 'hours', true), (12 + dst.diff), + 'hour diff across DST'); + assert.equal(b.diff(a, 'days', true), 12 / 24, 'day diff across DST'); + equal(assert, b.diff(a, 'weeks', true), 12 / 24 / 7, + 'week diff across DST'); + assert.ok(0.95 / (2 * 31) < b.diff(a, 'months', true), + 'month diff across DST, lower bound'); + assert.ok(b.diff(a, 'month', true) < 1.05 / (2 * 28), + 'month diff across DST, upper bound'); + assert.ok(0.95 / (2 * 31 * 12) < b.diff(a, 'years', true), + 'year diff across DST, lower bound'); + assert.ok(b.diff(a, 'year', true) < 1.05 / (2 * 28 * 12), + 'year diff across DST, upper bound'); + }); + + test('diff overflow', function (assert) { + assert.equal(moment([2011]).diff([2010], 'months'), 12, 'month diff'); + assert.equal(moment([2010, 0, 2]).diff([2010], 'hours'), 24, 'hour diff'); + assert.equal(moment([2010, 0, 1, 2]).diff([2010], 'minutes'), 120, 'minute diff'); + assert.equal(moment([2010, 0, 1, 0, 4]).diff([2010], 'seconds'), 240, 'second diff'); + }); + + test('diff between utc and local', function (assert) { + if (moment([2012]).utcOffset() === moment([2011]).utcOffset()) { + // Russia's utc offset on 1st of Jan 2012 vs 2011 is different + assert.equal(moment([2012]).utc().diff([2011], 'years'), 1, 'year diff'); + } + assert.equal(moment([2010, 2, 2]).utc().diff([2010, 0, 2], 'months'), 2, 'month diff'); + assert.equal(moment([2010, 0, 4]).utc().diff([2010], 'days'), 3, 'day diff'); + assert.equal(moment([2010, 0, 22]).utc().diff([2010], 'weeks'), 3, 'week diff'); + assert.equal(moment([2010, 0, 1, 4]).utc().diff([2010], 'hours'), 4, 'hour diff'); + assert.equal(moment([2010, 0, 1, 0, 5]).utc().diff([2010], 'minutes'), 5, 'minute diff'); + assert.equal(moment([2010, 0, 1, 0, 0, 6]).utc().diff([2010], 'seconds'), 6, 'second diff'); + }); + + test('diff floored', function (assert) { + assert.equal(moment([2010, 0, 1, 23]).diff([2010], 'day'), 0, '23 hours = 0 days'); + assert.equal(moment([2010, 0, 1, 23, 59]).diff([2010], 'day'), 0, '23:59 hours = 0 days'); + assert.equal(moment([2010, 0, 1, 24]).diff([2010], 'day'), 1, '24 hours = 1 day'); + assert.equal(moment([2010, 0, 2]).diff([2011, 0, 1], 'year'), 0, 'year rounded down'); + assert.equal(moment([2011, 0, 1]).diff([2010, 0, 2], 'year'), 0, 'year rounded down'); + assert.equal(moment([2010, 0, 2]).diff([2011, 0, 2], 'year'), -1, 'year rounded down'); + assert.equal(moment([2011, 0, 2]).diff([2010, 0, 2], 'year'), 1, 'year rounded down'); + }); + + test('year diffs include dates', function (assert) { + assert.ok(moment([2012, 1, 19]).diff(moment([2002, 1, 20]), 'years', true) < 10, 'year diff should include date of month'); + }); + + test('month diffs', function (assert) { + // due to floating point math errors, these tests just need to be accurate within 0.00000001 + assert.equal(moment([2012, 0, 1]).diff([2012, 1, 1], 'months', true), -1, 'Jan 1 to Feb 1 should be 1 month'); + equal(assert, 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'); + assert.equal(moment([2012, 0, 15]).diff([2012, 1, 15], 'months', true), -1, 'Jan 15 to Feb 15 should be 1 month'); + assert.equal(moment([2012, 0, 28]).diff([2012, 1, 28], 'months', true), -1, 'Jan 28 to Feb 28 should be 1 month'); + assert.ok(moment([2012, 0, 31]).diff([2012, 1, 29], 'months', true), -1, 'Jan 31 to Feb 29 should be 1 month'); + assert.ok(-1 > moment([2012, 0, 31]).diff([2012, 2, 1], 'months', true), 'Jan 31 to Mar 1 should be more than 1 month'); + assert.ok(-30 / 28 < moment([2012, 0, 31]).diff([2012, 2, 1], 'months', true), 'Jan 31 to Mar 1 should be less than 1 month and 1 day'); + equal(assert, moment([2012, 0, 1]).diff([2012, 0, 31], 'months', true), -(30 / 31), 'Jan 1 to Jan 31 should be 30 / 31 months'); + assert.ok(0 < moment('2014-02-01').diff(moment('2014-01-31'), 'months', true), 'jan-31 to feb-1 diff is positive'); + }); + + test('exact month diffs', function (assert) { + // generate all pairs of months and compute month diff, with fixed day + // of month = 15. + + var m1, m2; + for (m1 = 0; m1 < 12; ++m1) { + for (m2 = m1; m2 < 12; ++m2) { + assert.equal(moment([2013, m2, 15]).diff(moment([2013, m1, 15]), 'months', true), m2 - m1, + 'month diff from 2013-' + m1 + '-15 to 2013-' + m2 + '-15'); + } + } + }); + + test('year diffs', function (assert) { + // due to floating point math errors, these tests just need to be accurate within 0.00000001 + equal(assert, moment([2012, 0, 1]).diff([2013, 0, 1], 'years', true), -1, 'Jan 1 2012 to Jan 1 2013 should be 1 year'); + equal(assert, moment([2012, 1, 28]).diff([2013, 1, 28], 'years', true), -1, 'Feb 28 2012 to Feb 28 2013 should be 1 year'); + equal(assert, moment([2012, 2, 1]).diff([2013, 2, 1], 'years', true), -1, 'Mar 1 2012 to Mar 1 2013 should be 1 year'); + equal(assert, moment([2012, 11, 1]).diff([2013, 11, 1], 'years', true), -1, 'Dec 1 2012 to Dec 1 2013 should be 1 year'); + equal(assert, moment([2012, 11, 31]).diff([2013, 11, 31], 'years', true), -1, 'Dec 31 2012 to Dec 31 2013 should be 1 year'); + equal(assert, 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(assert, 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(assert, 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(assert, 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(assert, moment([2012, 1, 29]).diff([2013, 1, 28], 'years', true), -1, 'Feb 29 2012 to Feb 28 2013 should be 1-(1 / 28.5) / 12 years'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('duration'); + + test('object instantiation', function (assert) { + var d = moment.duration({ + years: 2, + months: 3, + weeks: 2, + days: 1, + hours: 8, + minutes: 9, + seconds: 20, + milliseconds: 12 + }); + + assert.equal(d.years(), 2, 'years'); + assert.equal(d.months(), 3, 'months'); + assert.equal(d.weeks(), 2, 'weeks'); + assert.equal(d.days(), 15, 'days'); // two weeks + 1 day + assert.equal(d.hours(), 8, 'hours'); + assert.equal(d.minutes(), 9, 'minutes'); + assert.equal(d.seconds(), 20, 'seconds'); + assert.equal(d.milliseconds(), 12, 'milliseconds'); + }); + + test('object instantiation with strings', function (assert) { + var d = moment.duration({ + years: '2', + months: '3', + weeks: '2', + days: '1', + hours: '8', + minutes: '9', + seconds: '20', + milliseconds: '12' + }); + + assert.equal(d.years(), 2, 'years'); + assert.equal(d.months(), 3, 'months'); + assert.equal(d.weeks(), 2, 'weeks'); + assert.equal(d.days(), 15, 'days'); // two weeks + 1 day + assert.equal(d.hours(), 8, 'hours'); + assert.equal(d.minutes(), 9, 'minutes'); + assert.equal(d.seconds(), 20, 'seconds'); + assert.equal(d.milliseconds(), 12, 'milliseconds'); + }); + + test('milliseconds instantiation', function (assert) { + assert.equal(moment.duration(72).milliseconds(), 72, 'milliseconds'); + }); + + test('undefined instantiation', function (assert) { + assert.equal(moment.duration(undefined).milliseconds(), 0, 'milliseconds'); + }); + + test('null instantiation', function (assert) { + assert.equal(moment.duration(null).milliseconds(), 0, 'milliseconds'); + }); + + test('instantiation by type', function (assert) { + assert.equal(moment.duration(1, 'years').years(), 1, 'years'); + assert.equal(moment.duration(1, 'y').years(), 1, 'y'); + assert.equal(moment.duration(2, 'months').months(), 2, 'months'); + assert.equal(moment.duration(2, 'M').months(), 2, 'M'); + assert.equal(moment.duration(3, 'weeks').weeks(), 3, 'weeks'); + assert.equal(moment.duration(3, 'w').weeks(), 3, 'weeks'); + assert.equal(moment.duration(4, 'days').days(), 4, 'days'); + assert.equal(moment.duration(4, 'd').days(), 4, 'd'); + assert.equal(moment.duration(5, 'hours').hours(), 5, 'hours'); + assert.equal(moment.duration(5, 'h').hours(), 5, 'h'); + assert.equal(moment.duration(6, 'minutes').minutes(), 6, 'minutes'); + assert.equal(moment.duration(6, 'm').minutes(), 6, 'm'); + assert.equal(moment.duration(7, 'seconds').seconds(), 7, 'seconds'); + assert.equal(moment.duration(7, 's').seconds(), 7, 's'); + assert.equal(moment.duration(8, 'milliseconds').milliseconds(), 8, 'milliseconds'); + assert.equal(moment.duration(8, 'ms').milliseconds(), 8, 'ms'); + }); + + test('shortcuts', function (assert) { + assert.equal(moment.duration({y: 1}).years(), 1, 'years = y'); + assert.equal(moment.duration({M: 2}).months(), 2, 'months = M'); + assert.equal(moment.duration({w: 3}).weeks(), 3, 'weeks = w'); + assert.equal(moment.duration({d: 4}).days(), 4, 'days = d'); + assert.equal(moment.duration({h: 5}).hours(), 5, 'hours = h'); + assert.equal(moment.duration({m: 6}).minutes(), 6, 'minutes = m'); + assert.equal(moment.duration({s: 7}).seconds(), 7, 'seconds = s'); + assert.equal(moment.duration({ms: 8}).milliseconds(), 8, 'milliseconds = ms'); + }); + + test('generic getter', function (assert) { + assert.equal(moment.duration(1, 'years').get('years'), 1, 'years'); + assert.equal(moment.duration(1, 'years').get('year'), 1, 'years = year'); + assert.equal(moment.duration(1, 'years').get('y'), 1, 'years = y'); + assert.equal(moment.duration(2, 'months').get('months'), 2, 'months'); + assert.equal(moment.duration(2, 'months').get('month'), 2, 'months = month'); + assert.equal(moment.duration(2, 'months').get('M'), 2, 'months = M'); + assert.equal(moment.duration(3, 'weeks').get('weeks'), 3, 'weeks'); + assert.equal(moment.duration(3, 'weeks').get('week'), 3, 'weeks = week'); + assert.equal(moment.duration(3, 'weeks').get('w'), 3, 'weeks = w'); + assert.equal(moment.duration(4, 'days').get('days'), 4, 'days'); + assert.equal(moment.duration(4, 'days').get('day'), 4, 'days = day'); + assert.equal(moment.duration(4, 'days').get('d'), 4, 'days = d'); + assert.equal(moment.duration(5, 'hours').get('hours'), 5, 'hours'); + assert.equal(moment.duration(5, 'hours').get('hour'), 5, 'hours = hour'); + assert.equal(moment.duration(5, 'hours').get('h'), 5, 'hours = h'); + assert.equal(moment.duration(6, 'minutes').get('minutes'), 6, 'minutes'); + assert.equal(moment.duration(6, 'minutes').get('minute'), 6, 'minutes = minute'); + assert.equal(moment.duration(6, 'minutes').get('m'), 6, 'minutes = m'); + assert.equal(moment.duration(7, 'seconds').get('seconds'), 7, 'seconds'); + assert.equal(moment.duration(7, 'seconds').get('second'), 7, 'seconds = second'); + assert.equal(moment.duration(7, 'seconds').get('s'), 7, 'seconds = s'); + assert.equal(moment.duration(8, 'milliseconds').get('milliseconds'), 8, 'milliseconds'); + assert.equal(moment.duration(8, 'milliseconds').get('millisecond'), 8, 'milliseconds = millisecond'); + assert.equal(moment.duration(8, 'milliseconds').get('ms'), 8, 'milliseconds = ms'); + }); + + test('instantiation from another duration', function (assert) { + 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 + }), + modified = moment.duration(1, 'day').add(moment.duration(1, 'day')); + + assert.deepEqual(moment.duration(simple), simple, 'simple clones are equal'); + assert.deepEqual(moment.duration(lengthy), lengthy, 'lengthy clones are equal'); + assert.deepEqual(moment.duration(complicated), complicated, 'complicated clones are equal'); + assert.deepEqual(moment.duration(modified), modified, 'cloning modified duration works'); + }); + + test('instantiation from 24-hour time zero', function (assert) { + assert.equal(moment.duration('00:00').years(), 0, '0 years'); + assert.equal(moment.duration('00:00').days(), 0, '0 days'); + assert.equal(moment.duration('00:00').hours(), 0, '0 hours'); + assert.equal(moment.duration('00:00').minutes(), 0, '0 minutes'); + assert.equal(moment.duration('00:00').seconds(), 0, '0 seconds'); + assert.equal(moment.duration('00:00').milliseconds(), 0, '0 milliseconds'); + }); + + test('instantiation from 24-hour time <24 hours', function (assert) { + assert.equal(moment.duration('06:45').years(), 0, '0 years'); + assert.equal(moment.duration('06:45').days(), 0, '0 days'); + assert.equal(moment.duration('06:45').hours(), 6, '6 hours'); + assert.equal(moment.duration('06:45').minutes(), 45, '45 minutes'); + assert.equal(moment.duration('06:45').seconds(), 0, '0 seconds'); + assert.equal(moment.duration('06:45').milliseconds(), 0, '0 milliseconds'); + }); + + test('instantiation from 24-hour time >24 hours', function (assert) { + assert.equal(moment.duration('26:45').years(), 0, '0 years'); + assert.equal(moment.duration('26:45').days(), 1, '0 days'); + assert.equal(moment.duration('26:45').hours(), 2, '2 hours'); + assert.equal(moment.duration('26:45').minutes(), 45, '45 minutes'); + assert.equal(moment.duration('26:45').seconds(), 0, '0 seconds'); + assert.equal(moment.duration('26:45').milliseconds(), 0, '0 milliseconds'); + }); + + test('instatiation from serialized C# TimeSpan zero', function (assert) { + assert.equal(moment.duration('00:00:00').years(), 0, '0 years'); + assert.equal(moment.duration('00:00:00').days(), 0, '0 days'); + assert.equal(moment.duration('00:00:00').hours(), 0, '0 hours'); + assert.equal(moment.duration('00:00:00').minutes(), 0, '0 minutes'); + assert.equal(moment.duration('00:00:00').seconds(), 0, '0 seconds'); + assert.equal(moment.duration('00:00:00').milliseconds(), 0, '0 milliseconds'); + }); + + test('instatiation from serialized C# TimeSpan with days', function (assert) { + assert.equal(moment.duration('1.02:03:04.9999999').years(), 0, '0 years'); + assert.equal(moment.duration('1.02:03:04.9999999').days(), 1, '1 day'); + assert.equal(moment.duration('1.02:03:04.9999999').hours(), 2, '2 hours'); + assert.equal(moment.duration('1.02:03:04.9999999').minutes(), 3, '3 minutes'); + assert.equal(moment.duration('1.02:03:04.9999999').seconds(), 4, '4 seconds'); + assert.equal(moment.duration('1.02:03:04.9999999').milliseconds(), 999, '999 milliseconds'); + }); + + test('instatiation from serialized C# TimeSpan without days', function (assert) { + assert.equal(moment.duration('01:02:03.9999999').years(), 0, '0 years'); + assert.equal(moment.duration('01:02:03.9999999').days(), 0, '0 days'); + assert.equal(moment.duration('01:02:03.9999999').hours(), 1, '1 hour'); + assert.equal(moment.duration('01:02:03.9999999').minutes(), 2, '2 minutes'); + assert.equal(moment.duration('01:02:03.9999999').seconds(), 3, '3 seconds'); + assert.equal(moment.duration('01:02:03.9999999').milliseconds(), 999, '999 milliseconds'); + + assert.equal(moment.duration('23:59:59.9999999').days(), 0, '0 days'); + assert.equal(moment.duration('23:59:59.9999999').hours(), 23, '23 hours'); + + assert.equal(moment.duration('500:59:59.9999999').days(), 20, '500 hours overflows to 20 days'); + assert.equal(moment.duration('500:59:59.9999999').hours(), 20, '500 hours overflows to 20 hours'); + }); + + test('instatiation from serialized C# TimeSpan without days or milliseconds', function (assert) { + assert.equal(moment.duration('01:02:03').years(), 0, '0 years'); + assert.equal(moment.duration('01:02:03').days(), 0, '0 days'); + assert.equal(moment.duration('01:02:03').hours(), 1, '1 hour'); + assert.equal(moment.duration('01:02:03').minutes(), 2, '2 minutes'); + assert.equal(moment.duration('01:02:03').seconds(), 3, '3 seconds'); + assert.equal(moment.duration('01:02:03').milliseconds(), 0, '0 milliseconds'); + }); + + test('instatiation from serialized C# TimeSpan without milliseconds', function (assert) { + assert.equal(moment.duration('1.02:03:04').years(), 0, '0 years'); + assert.equal(moment.duration('1.02:03:04').days(), 1, '1 day'); + assert.equal(moment.duration('1.02:03:04').hours(), 2, '2 hours'); + assert.equal(moment.duration('1.02:03:04').minutes(), 3, '3 minutes'); + assert.equal(moment.duration('1.02:03:04').seconds(), 4, '4 seconds'); + assert.equal(moment.duration('1.02:03:04').milliseconds(), 0, '0 milliseconds'); + }); + + test('instatiation from serialized C# TimeSpan maxValue', function (assert) { + var d = moment.duration('10675199.02:48:05.4775807'); + + assert.equal(d.years(), 29227, '29227 years'); + assert.equal(d.months(), 8, '8 months'); + assert.equal(d.days(), 17, '17 day'); // this should be 13 + + assert.equal(d.hours(), 2, '2 hours'); + assert.equal(d.minutes(), 48, '48 minutes'); + assert.equal(d.seconds(), 5, '5 seconds'); + assert.equal(d.milliseconds(), 477, '477 milliseconds'); + }); + + test('instatiation from serialized C# TimeSpan minValue', function (assert) { + var d = moment.duration('-10675199.02:48:05.4775808'); + + assert.equal(d.years(), -29227, '29653 years'); + assert.equal(d.months(), -8, '8 day'); + assert.equal(d.days(), -17, '17 day'); // this should be 13 + + assert.equal(d.hours(), -2, '2 hours'); + assert.equal(d.minutes(), -48, '48 minutes'); + assert.equal(d.seconds(), -5, '5 seconds'); + assert.equal(d.milliseconds(), -477, '477 milliseconds'); + }); + + test('instantiation from ISO 8601 duration', function (assert) { + assert.equal(moment.duration('P1Y2M3DT4H5M6S').asSeconds(), moment.duration({y: 1, M: 2, d: 3, h: 4, m: 5, s: 6}).asSeconds(), 'all fields'); + assert.equal(moment.duration('P1M').asSeconds(), moment.duration({M: 1}).asSeconds(), 'single month field'); + assert.equal(moment.duration('PT1M').asSeconds(), moment.duration({m: 1}).asSeconds(), 'single minute field'); + assert.equal(moment.duration('P1MT2H').asSeconds(), moment.duration({M: 1, h: 2}).asSeconds(), 'random fields missing'); + assert.equal(moment.duration('-P60D').asSeconds(), moment.duration({d: -60}).asSeconds(), 'negative days'); + assert.equal(moment.duration('PT0.5S').asSeconds(), moment.duration({s: 0.5}).asSeconds(), 'fractional seconds'); + assert.equal(moment.duration('PT0,5S').asSeconds(), moment.duration({s: 0.5}).asSeconds(), 'fractional seconds (comma)'); + }); + + test('serialization to ISO 8601 duration strings', function (assert) { + assert.equal(moment.duration({y: 1, M: 2, d: 3, h: 4, m: 5, s: 6}).toISOString(), 'P1Y2M3DT4H5M6S', 'all fields'); + assert.equal(moment.duration({M: -1}).toISOString(), '-P1M', 'one month ago'); + assert.equal(moment.duration({m: -1}).toISOString(), '-PT1M', 'one minute ago'); + assert.equal(moment.duration({s: -0.5}).toISOString(), '-PT0.5S', 'one half second ago'); + assert.equal(moment.duration({y: -0.5, M: 1}).toISOString(), '-P5M', 'a month after half a year ago'); + assert.equal(moment.duration({}).toISOString(), 'P0D', 'zero duration'); + }); + + test('toString acts as toISOString', function (assert) { + assert.equal(moment.duration({y: 1, M: 2, d: 3, h: 4, m: 5, s: 6}).toString(), 'P1Y2M3DT4H5M6S', 'all fields'); + assert.equal(moment.duration({M: -1}).toString(), '-P1M', 'one month ago'); + assert.equal(moment.duration({m: -1}).toString(), '-PT1M', 'one minute ago'); + assert.equal(moment.duration({s: -0.5}).toString(), '-PT0.5S', 'one half second ago'); + assert.equal(moment.duration({y: -0.5, M: 1}).toString(), '-P5M', 'a month after half a year ago'); + assert.equal(moment.duration({}).toString(), 'P0D', 'zero duration'); + }); + + test('toIsoString deprecation', function (assert) { + assert.equal(moment.duration({}).toIsoString(), moment.duration({}).toISOString(), 'toIsoString delegates to toISOString'); + }); + + test('`isodate` (python) test cases', function (assert) { + assert.equal(moment.duration('P18Y9M4DT11H9M8S').asSeconds(), moment.duration({y: 18, M: 9, d: 4, h: 11, m: 9, s: 8}).asSeconds(), 'python isodate 1'); + assert.equal(moment.duration('P2W').asSeconds(), moment.duration({w: 2}).asSeconds(), 'python isodate 2'); + assert.equal(moment.duration('P3Y6M4DT12H30M5S').asSeconds(), moment.duration({y: 3, M: 6, d: 4, h: 12, m: 30, s: 5}).asSeconds(), 'python isodate 3'); + assert.equal(moment.duration('P23DT23H').asSeconds(), moment.duration({d: 23, h: 23}).asSeconds(), 'python isodate 4'); + assert.equal(moment.duration('P4Y').asSeconds(), moment.duration({y: 4}).asSeconds(), 'python isodate 5'); + assert.equal(moment.duration('P1M').asSeconds(), moment.duration({M: 1}).asSeconds(), 'python isodate 6'); + assert.equal(moment.duration('PT1M').asSeconds(), moment.duration({m: 1}).asSeconds(), 'python isodate 7'); + assert.equal(moment.duration('P0.5Y').asSeconds(), moment.duration({y: 0.5}).asSeconds(), 'python isodate 8'); + assert.equal(moment.duration('PT36H').asSeconds(), moment.duration({h: 36}).asSeconds(), 'python isodate 9'); + assert.equal(moment.duration('P1DT12H').asSeconds(), moment.duration({d: 1, h: 12}).asSeconds(), 'python isodate 10'); + assert.equal(moment.duration('-P2W').asSeconds(), moment.duration({w: -2}).asSeconds(), 'python isodate 11'); + assert.equal(moment.duration('-P2.2W').asSeconds(), moment.duration({w: -2.2}).asSeconds(), 'python isodate 12'); + assert.equal(moment.duration('P1DT2H3M4S').asSeconds(), moment.duration({d: 1, h: 2, m: 3, s: 4}).asSeconds(), 'python isodate 13'); + assert.equal(moment.duration('P1DT2H3M').asSeconds(), moment.duration({d: 1, h: 2, m: 3}).asSeconds(), 'python isodate 14'); + assert.equal(moment.duration('P1DT2H').asSeconds(), moment.duration({d: 1, h: 2}).asSeconds(), 'python isodate 15'); + assert.equal(moment.duration('PT2H').asSeconds(), moment.duration({h: 2}).asSeconds(), 'python isodate 16'); + assert.equal(moment.duration('PT2.3H').asSeconds(), moment.duration({h: 2.3}).asSeconds(), 'python isodate 17'); + assert.equal(moment.duration('PT2H3M4S').asSeconds(), moment.duration({h: 2, m: 3, s: 4}).asSeconds(), 'python isodate 18'); + assert.equal(moment.duration('PT3M4S').asSeconds(), moment.duration({m: 3, s: 4}).asSeconds(), 'python isodate 19'); + assert.equal(moment.duration('PT22S').asSeconds(), moment.duration({s: 22}).asSeconds(), 'python isodate 20'); + assert.equal(moment.duration('PT22.22S').asSeconds(), moment.duration({s: 22.22}).asSeconds(), 'python isodate 21'); + assert.equal(moment.duration('-P2Y').asSeconds(), moment.duration({y: -2}).asSeconds(), 'python isodate 22'); + assert.equal(moment.duration('-P3Y6M4DT12H30M5S').asSeconds(), moment.duration({y: -3, M: -6, d: -4, h: -12, m: -30, s: -5}).asSeconds(), 'python isodate 23'); + assert.equal(moment.duration('-P1DT2H3M4S').asSeconds(), moment.duration({d: -1, h: -2, m: -3, s: -4}).asSeconds(), 'python isodate 24'); + }); + + test('ISO 8601 misuse cases', function (assert) { + assert.equal(moment.duration('P').asSeconds(), 0, 'lonely P'); + assert.equal(moment.duration('PT').asSeconds(), 0, 'just P and T'); + assert.equal(moment.duration('P1H').asSeconds(), 0, 'missing T'); + assert.equal(moment.duration('P1D1Y').asSeconds(), 0, 'out of order'); + assert.equal(moment.duration('PT.5S').asSeconds(), 0.5, 'accept no leading zero for decimal'); + assert.equal(moment.duration('PT1,S').asSeconds(), 1, 'accept trailing decimal separator'); + assert.equal(moment.duration('PT1M0,,5S').asSeconds(), 60, 'extra decimal separators are ignored as 0'); + assert.equal(moment.duration('P-1DS').asSeconds(), 0, 'wrong position of negative'); + }); + + test('humanize', function (assert) { + moment.locale('en'); + assert.equal(moment.duration({seconds: 44}).humanize(), 'a few seconds', '44 seconds = a few seconds'); + assert.equal(moment.duration({seconds: 45}).humanize(), 'a minute', '45 seconds = a minute'); + assert.equal(moment.duration({seconds: 89}).humanize(), 'a minute', '89 seconds = a minute'); + assert.equal(moment.duration({seconds: 90}).humanize(), '2 minutes', '90 seconds = 2 minutes'); + assert.equal(moment.duration({minutes: 44}).humanize(), '44 minutes', '44 minutes = 44 minutes'); + assert.equal(moment.duration({minutes: 45}).humanize(), 'an hour', '45 minutes = an hour'); + assert.equal(moment.duration({minutes: 89}).humanize(), 'an hour', '89 minutes = an hour'); + assert.equal(moment.duration({minutes: 90}).humanize(), '2 hours', '90 minutes = 2 hours'); + assert.equal(moment.duration({hours: 5}).humanize(), '5 hours', '5 hours = 5 hours'); + assert.equal(moment.duration({hours: 21}).humanize(), '21 hours', '21 hours = 21 hours'); + assert.equal(moment.duration({hours: 22}).humanize(), 'a day', '22 hours = a day'); + assert.equal(moment.duration({hours: 35}).humanize(), 'a day', '35 hours = a day'); + assert.equal(moment.duration({hours: 36}).humanize(), '2 days', '36 hours = 2 days'); + assert.equal(moment.duration({days: 1}).humanize(), 'a day', '1 day = a day'); + assert.equal(moment.duration({days: 5}).humanize(), '5 days', '5 days = 5 days'); + assert.equal(moment.duration({weeks: 1}).humanize(), '7 days', '1 week = 7 days'); + assert.equal(moment.duration({days: 25}).humanize(), '25 days', '25 days = 25 days'); + assert.equal(moment.duration({days: 26}).humanize(), 'a month', '26 days = a month'); + assert.equal(moment.duration({days: 30}).humanize(), 'a month', '30 days = a month'); + assert.equal(moment.duration({days: 45}).humanize(), 'a month', '45 days = a month'); + assert.equal(moment.duration({days: 46}).humanize(), '2 months', '46 days = 2 months'); + assert.equal(moment.duration({days: 74}).humanize(), '2 months', '74 days = 2 months'); + assert.equal(moment.duration({days: 77}).humanize(), '3 months', '77 days = 3 months'); + assert.equal(moment.duration({months: 1}).humanize(), 'a month', '1 month = a month'); + assert.equal(moment.duration({months: 5}).humanize(), '5 months', '5 months = 5 months'); + assert.equal(moment.duration({days: 344}).humanize(), 'a year', '344 days = a year'); + assert.equal(moment.duration({days: 345}).humanize(), 'a year', '345 days = a year'); + assert.equal(moment.duration({days: 547}).humanize(), 'a year', '547 days = a year'); + assert.equal(moment.duration({days: 548}).humanize(), '2 years', '548 days = 2 years'); + assert.equal(moment.duration({years: 1}).humanize(), 'a year', '1 year = a year'); + assert.equal(moment.duration({years: 5}).humanize(), '5 years', '5 years = 5 years'); + assert.equal(moment.duration(7200000).humanize(), '2 hours', '7200000 = 2 minutes'); + }); + + test('humanize duration with suffix', function (assert) { + moment.locale('en'); + assert.equal(moment.duration({seconds: 44}).humanize(true), 'in a few seconds', '44 seconds = a few seconds'); + assert.equal(moment.duration({seconds: -44}).humanize(true), 'a few seconds ago', '44 seconds = a few seconds'); + }); + + test('bubble value up', function (assert) { + assert.equal(moment.duration({milliseconds: 61001}).milliseconds(), 1, '61001 milliseconds has 1 millisecond left over'); + assert.equal(moment.duration({milliseconds: 61001}).seconds(), 1, '61001 milliseconds has 1 second left over'); + assert.equal(moment.duration({milliseconds: 61001}).minutes(), 1, '61001 milliseconds has 1 minute left over'); + + assert.equal(moment.duration({minutes: 350}).minutes(), 50, '350 minutes has 50 minutes left over'); + assert.equal(moment.duration({minutes: 350}).hours(), 5, '350 minutes has 5 hours left over'); + }); + + test('clipping', function (assert) { + assert.equal(moment.duration({months: 11}).months(), 11, '11 months is 11 months'); + assert.equal(moment.duration({months: 11}).years(), 0, '11 months makes no year'); + assert.equal(moment.duration({months: 12}).months(), 0, '12 months is 0 months left over'); + assert.equal(moment.duration({months: 12}).years(), 1, '12 months makes 1 year'); + assert.equal(moment.duration({months: 13}).months(), 1, '13 months is 1 month left over'); + assert.equal(moment.duration({months: 13}).years(), 1, '13 months makes 1 year'); + + assert.equal(moment.duration({days: 29}).days(), 29, '29 days is 29 days'); + assert.equal(moment.duration({days: 29}).months(), 0, '29 days makes no month'); + assert.equal(moment.duration({days: 30}).days(), 0, '30 days is 0 days left over'); + assert.equal(moment.duration({days: 30}).months(), 1, '30 days is a month'); + assert.equal(moment.duration({days: 31}).days(), 1, '31 days is 1 day left over'); + assert.equal(moment.duration({days: 31}).months(), 1, '31 days is a month'); + + assert.equal(moment.duration({hours: 23}).hours(), 23, '23 hours is 23 hours'); + assert.equal(moment.duration({hours: 23}).days(), 0, '23 hours makes no day'); + assert.equal(moment.duration({hours: 24}).hours(), 0, '24 hours is 0 hours left over'); + assert.equal(moment.duration({hours: 24}).days(), 1, '24 hours makes 1 day'); + assert.equal(moment.duration({hours: 25}).hours(), 1, '25 hours is 1 hour left over'); + assert.equal(moment.duration({hours: 25}).days(), 1, '25 hours makes 1 day'); + }); + + test('effective equivalency', function (assert) { + assert.deepEqual(moment.duration({seconds: 1})._data, moment.duration({milliseconds: 1000})._data, '1 second is the same as 1000 milliseconds'); + assert.deepEqual(moment.duration({seconds: 60})._data, moment.duration({minutes: 1})._data, '1 minute is the same as 60 seconds'); + assert.deepEqual(moment.duration({minutes: 60})._data, moment.duration({hours: 1})._data, '1 hour is the same as 60 minutes'); + assert.deepEqual(moment.duration({hours: 24})._data, moment.duration({days: 1})._data, '1 day is the same as 24 hours'); + assert.deepEqual(moment.duration({days: 7})._data, moment.duration({weeks: 1})._data, '1 week is the same as 7 days'); + assert.deepEqual(moment.duration({days: 30})._data, moment.duration({months: 1})._data, '1 month is the same as 30 days'); + assert.deepEqual(moment.duration({months: 12})._data, moment.duration({years: 1})._data, '1 years is the same as 12 months'); + }); + + test('asGetters', function (assert) { + // 400 years have exactly 146097 days + + // years + assert.equal(moment.duration(1, 'year').asYears(), 1, '1 year as years'); + assert.equal(moment.duration(1, 'year').asMonths(), 12, '1 year as months'); + assert.equal(moment.duration(400, 'year').asMonths(), 4800, '400 years as months'); + assert.equal(moment.duration(1, 'year').asWeeks().toFixed(3), 52.143, '1 year as weeks'); + assert.equal(moment.duration(1, 'year').asDays(), 365, '1 year as days'); + assert.equal(moment.duration(2, 'year').asDays(), 730, '2 years as days'); + assert.equal(moment.duration(3, 'year').asDays(), 1096, '3 years as days'); + assert.equal(moment.duration(4, 'year').asDays(), 1461, '4 years as days'); + assert.equal(moment.duration(400, 'year').asDays(), 146097, '400 years as days'); + assert.equal(moment.duration(1, 'year').asHours(), 8760, '1 year as hours'); + assert.equal(moment.duration(1, 'year').asMinutes(), 525600, '1 year as minutes'); + assert.equal(moment.duration(1, 'year').asSeconds(), 31536000, '1 year as seconds'); + assert.equal(moment.duration(1, 'year').asMilliseconds(), 31536000000, '1 year as milliseconds'); + + // months + assert.equal(moment.duration(1, 'month').asYears().toFixed(4), 0.0833, '1 month as years'); + assert.equal(moment.duration(1, 'month').asMonths(), 1, '1 month as months'); + assert.equal(moment.duration(1, 'month').asWeeks().toFixed(3), 4.286, '1 month as weeks'); + assert.equal(moment.duration(1, 'month').asDays(), 30, '1 month as days'); + assert.equal(moment.duration(2, 'month').asDays(), 61, '2 months as days'); + assert.equal(moment.duration(3, 'month').asDays(), 91, '3 months as days'); + assert.equal(moment.duration(4, 'month').asDays(), 122, '4 months as days'); + assert.equal(moment.duration(5, 'month').asDays(), 152, '5 months as days'); + assert.equal(moment.duration(6, 'month').asDays(), 183, '6 months as days'); + assert.equal(moment.duration(7, 'month').asDays(), 213, '7 months as days'); + assert.equal(moment.duration(8, 'month').asDays(), 243, '8 months as days'); + assert.equal(moment.duration(9, 'month').asDays(), 274, '9 months as days'); + assert.equal(moment.duration(10, 'month').asDays(), 304, '10 months as days'); + assert.equal(moment.duration(11, 'month').asDays(), 335, '11 months as days'); + assert.equal(moment.duration(12, 'month').asDays(), 365, '12 months as days'); + assert.equal(moment.duration(24, 'month').asDays(), 730, '24 months as days'); + assert.equal(moment.duration(36, 'month').asDays(), 1096, '36 months as days'); + assert.equal(moment.duration(48, 'month').asDays(), 1461, '48 months as days'); + assert.equal(moment.duration(4800, 'month').asDays(), 146097, '4800 months as days'); + assert.equal(moment.duration(1, 'month').asHours(), 720, '1 month as hours'); + assert.equal(moment.duration(1, 'month').asMinutes(), 43200, '1 month as minutes'); + assert.equal(moment.duration(1, 'month').asSeconds(), 2592000, '1 month as seconds'); + assert.equal(moment.duration(1, 'month').asMilliseconds(), 2592000000, '1 month as milliseconds'); + + // weeks + assert.equal(moment.duration(1, 'week').asYears().toFixed(4), 0.0192, '1 week as years'); + assert.equal(moment.duration(1, 'week').asMonths().toFixed(3), 0.230, '1 week as months'); + assert.equal(moment.duration(1, 'week').asWeeks(), 1, '1 week as weeks'); + assert.equal(moment.duration(1, 'week').asDays(), 7, '1 week as days'); + assert.equal(moment.duration(1, 'week').asHours(), 168, '1 week as hours'); + assert.equal(moment.duration(1, 'week').asMinutes(), 10080, '1 week as minutes'); + assert.equal(moment.duration(1, 'week').asSeconds(), 604800, '1 week as seconds'); + assert.equal(moment.duration(1, 'week').asMilliseconds(), 604800000, '1 week as milliseconds'); + + // days + assert.equal(moment.duration(1, 'day').asYears().toFixed(4), 0.0027, '1 day as years'); + assert.equal(moment.duration(1, 'day').asMonths().toFixed(3), 0.033, '1 day as months'); + assert.equal(moment.duration(1, 'day').asWeeks().toFixed(3), 0.143, '1 day as weeks'); + assert.equal(moment.duration(1, 'day').asDays(), 1, '1 day as days'); + assert.equal(moment.duration(1, 'day').asHours(), 24, '1 day as hours'); + assert.equal(moment.duration(1, 'day').asMinutes(), 1440, '1 day as minutes'); + assert.equal(moment.duration(1, 'day').asSeconds(), 86400, '1 day as seconds'); + assert.equal(moment.duration(1, 'day').asMilliseconds(), 86400000, '1 day as milliseconds'); + + // hours + assert.equal(moment.duration(1, 'hour').asYears().toFixed(6), 0.000114, '1 hour as years'); + assert.equal(moment.duration(1, 'hour').asMonths().toFixed(5), 0.00137, '1 hour as months'); + assert.equal(moment.duration(1, 'hour').asWeeks().toFixed(5), 0.00595, '1 hour as weeks'); + assert.equal(moment.duration(1, 'hour').asDays().toFixed(4), 0.0417, '1 hour as days'); + assert.equal(moment.duration(1, 'hour').asHours(), 1, '1 hour as hours'); + assert.equal(moment.duration(1, 'hour').asMinutes(), 60, '1 hour as minutes'); + assert.equal(moment.duration(1, 'hour').asSeconds(), 3600, '1 hour as seconds'); + assert.equal(moment.duration(1, 'hour').asMilliseconds(), 3600000, '1 hour as milliseconds'); + + // minutes + assert.equal(moment.duration(1, 'minute').asYears().toFixed(8), 0.00000190, '1 minute as years'); + assert.equal(moment.duration(1, 'minute').asMonths().toFixed(7), 0.0000228, '1 minute as months'); + assert.equal(moment.duration(1, 'minute').asWeeks().toFixed(7), 0.0000992, '1 minute as weeks'); + assert.equal(moment.duration(1, 'minute').asDays().toFixed(6), 0.000694, '1 minute as days'); + assert.equal(moment.duration(1, 'minute').asHours().toFixed(4), 0.0167, '1 minute as hours'); + assert.equal(moment.duration(1, 'minute').asMinutes(), 1, '1 minute as minutes'); + assert.equal(moment.duration(1, 'minute').asSeconds(), 60, '1 minute as seconds'); + assert.equal(moment.duration(1, 'minute').asMilliseconds(), 60000, '1 minute as milliseconds'); + + // seconds + assert.equal(moment.duration(1, 'second').asYears().toFixed(10), 0.0000000317, '1 second as years'); + assert.equal(moment.duration(1, 'second').asMonths().toFixed(9), 0.000000380, '1 second as months'); + assert.equal(moment.duration(1, 'second').asWeeks().toFixed(8), 0.00000165, '1 second as weeks'); + assert.equal(moment.duration(1, 'second').asDays().toFixed(7), 0.0000116, '1 second as days'); + assert.equal(moment.duration(1, 'second').asHours().toFixed(6), 0.000278, '1 second as hours'); + assert.equal(moment.duration(1, 'second').asMinutes().toFixed(4), 0.0167, '1 second as minutes'); + assert.equal(moment.duration(1, 'second').asSeconds(), 1, '1 second as seconds'); + assert.equal(moment.duration(1, 'second').asMilliseconds(), 1000, '1 second as milliseconds'); + + // milliseconds + assert.equal(moment.duration(1, 'millisecond').asYears().toFixed(13), 0.0000000000317, '1 millisecond as years'); + assert.equal(moment.duration(1, 'millisecond').asMonths().toFixed(12), 0.000000000380, '1 millisecond as months'); + assert.equal(moment.duration(1, 'millisecond').asWeeks().toFixed(11), 0.00000000165, '1 millisecond as weeks'); + assert.equal(moment.duration(1, 'millisecond').asDays().toFixed(10), 0.0000000116, '1 millisecond as days'); + assert.equal(moment.duration(1, 'millisecond').asHours().toFixed(9), 0.000000278, '1 millisecond as hours'); + assert.equal(moment.duration(1, 'millisecond').asMinutes().toFixed(7), 0.0000167, '1 millisecond as minutes'); + assert.equal(moment.duration(1, 'millisecond').asSeconds(), 0.001, '1 millisecond as seconds'); + assert.equal(moment.duration(1, 'millisecond').asMilliseconds(), 1, '1 millisecond as milliseconds'); + }); + + test('as getters for small units', function (assert) { + var dS = moment.duration(1, 'milliseconds'), + ds = moment.duration(3, 'seconds'), + dm = moment.duration(13, 'minutes'); + + // Tests for issue #1867. + // Floating point errors for small duration units were introduced in version 2.8.0. + assert.equal(dS.as('milliseconds'), 1, 'as("milliseconds")'); + assert.equal(dS.asMilliseconds(), 1, 'asMilliseconds()'); + assert.equal(ds.as('seconds'), 3, 'as("seconds")'); + assert.equal(ds.asSeconds(), 3, 'asSeconds()'); + assert.equal(dm.as('minutes'), 13, 'as("minutes")'); + assert.equal(dm.asMinutes(), 13, 'asMinutes()'); + }); + + test('isDuration', function (assert) { + assert.ok(moment.isDuration(moment.duration(12345678)), 'correctly says true'); + assert.ok(!moment.isDuration(moment()), 'moment object is not a duration'); + assert.ok(!moment.isDuration({milliseconds: 1}), 'plain object is not a duration'); + }); + + test('add', function (assert) { + var d = moment.duration({months: 4, weeks: 3, days: 2}); + // for some reason, d._data._months does not get updated; use d._months instead. + assert.equal(d.add(1, 'month')._months, 5, 'Add months'); + assert.equal(d.add(5, 'days')._days, 28, 'Add days'); + assert.equal(d.add(10000)._milliseconds, 10000, 'Add milliseconds'); + assert.equal(d.add({h: 23, m: 59})._milliseconds, 23 * 60 * 60 * 1000 + 59 * 60 * 1000 + 10000, 'Add hour:minute'); + }); + + test('add and bubble', function (assert) { + assert.equal(moment.duration(1, 'second').add(1000, 'milliseconds').seconds(), 2, 'Adding milliseconds should bubble up to seconds'); + assert.equal(moment.duration(1, 'minute').add(60, 'second').minutes(), 2, 'Adding seconds should bubble up to minutes'); + assert.equal(moment.duration(1, 'hour').add(60, 'minutes').hours(), 2, 'Adding minutes should bubble up to hours'); + assert.equal(moment.duration(1, 'day').add(24, 'hours').days(), 2, 'Adding hours should bubble up to days'); + }); + + test('subtract and bubble', function (assert) { + assert.equal(moment.duration(2, 'second').subtract(1000, 'milliseconds').seconds(), 1, 'Subtracting milliseconds should bubble up to seconds'); + assert.equal(moment.duration(2, 'minute').subtract(60, 'second').minutes(), 1, 'Subtracting seconds should bubble up to minutes'); + assert.equal(moment.duration(2, 'hour').subtract(60, 'minutes').hours(), 1, 'Subtracting minutes should bubble up to hours'); + assert.equal(moment.duration(2, 'day').subtract(24, 'hours').days(), 1, 'Subtracting hours should bubble up to days'); + }); + + test('subtract', function (assert) { + 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. + assert.equal(d.subtract(1, 'months')._months, 1, 'Subtract months'); + assert.equal(d.subtract(14, 'days')._days, 0, 'Subtract days'); + assert.equal(d.subtract(10000)._milliseconds, 5 * 60 * 60 * 1000 - 10000, 'Subtract milliseconds'); + assert.equal(d.subtract({h: 1, m: 59})._milliseconds, 3 * 60 * 60 * 1000 + 1 * 60 * 1000 - 10000, 'Subtract hour:minute'); + }); + + test('JSON.stringify duration', function (assert) { + var d = moment.duration(1024, 'h'); + + assert.equal(JSON.stringify(d), '"' + d.toISOString() + '"', 'JSON.stringify on duration should return ISO string'); + }); + + test('duration plugins', function (assert) { + var durationObject = moment.duration(); + moment.duration.fn.foo = function (arg) { + assert.equal(this, durationObject); + assert.equal(arg, 5); + }; + durationObject.foo(5); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('duration from moments'); + + test('pure year diff', function (assert) { + var m1 = moment('2012-01-01T00:00:00.000Z'), + m2 = moment('2013-01-01T00:00:00.000Z'); + + assert.equal(moment.duration({from: m1, to: m2}).as('years'), 1, 'year moment difference'); + assert.equal(moment.duration({from: m2, to: m1}).as('years'), -1, 'negative year moment difference'); + }); + + test('month and day diff', function (assert) { + var m1 = moment('2012-01-15T00:00:00.000Z'), + m2 = moment('2012-02-17T00:00:00.000Z'), + d = moment.duration({from: m1, to: m2}); + + assert.equal(d.get('days'), 2); + assert.equal(d.get('months'), 1); + }); + + test('day diff, separate months', function (assert) { + var m1 = moment('2012-01-15T00:00:00.000Z'), + m2 = moment('2012-02-13T00:00:00.000Z'), + d = moment.duration({from: m1, to: m2}); + + assert.equal(d.as('days'), 29); + }); + + test('hour diff', function (assert) { + var m1 = moment('2012-01-15T17:00:00.000Z'), + m2 = moment('2012-01-16T03:00:00.000Z'), + d = moment.duration({from: m1, to: m2}); + + assert.equal(d.as('hours'), 10); + }); + + test('minute diff', function (assert) { + var m1 = moment('2012-01-15T17:45:00.000Z'), + m2 = moment('2012-01-16T03:15:00.000Z'), + d = moment.duration({from: m1, to: m2}); + + assert.equal(d.as('hours'), 9.5); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('format'); + + test('format YY', function (assert) { + var b = moment(new Date(2009, 1, 14, 15, 25, 50, 125)); + assert.equal(b.format('YY'), '09', 'YY ---> 09'); + }); + + test('format escape brackets', function (assert) { + moment.locale('en'); + + var b = moment(new Date(2009, 1, 14, 15, 25, 50, 125)); + assert.equal(b.format('[day]'), 'day', 'Single bracket'); + assert.equal(b.format('[day] YY [YY]'), 'day 09 YY', 'Double bracket'); + assert.equal(b.format('[YY'), '[09', 'Un-ended bracket'); + assert.equal(b.format('[[YY]]'), '[YY]', 'Double nested brackets'); + assert.equal(b.format('[[]'), '[', 'Escape open bracket'); + assert.equal(b.format('[Last]'), 'Last', 'localized tokens'); + assert.equal(b.format('[L] L'), 'L 02/14/2009', 'localized tokens with escaped localized tokens'); + assert.equal(b.format('[L LL LLL LLLL aLa]'), 'L LL LLL LLLL aLa', 'localized tokens with escaped localized tokens'); + assert.equal(b.format('[LLL] LLL'), 'LLL February 14, 2009 3:25 PM', 'localized tokens with escaped localized tokens (recursion)'); + assert.equal(b.format('YYYY[\n]DD[\n]'), '2009\n14\n', 'Newlines'); + }); + + test('handle negative years', function (assert) { + moment.locale('en'); + assert.equal(moment.utc().year(-1).format('YY'), '-01', 'YY with negative year'); + assert.equal(moment.utc().year(-1).format('YYYY'), '-0001', 'YYYY with negative year'); + assert.equal(moment.utc().year(-12).format('YY'), '-12', 'YY with negative year'); + assert.equal(moment.utc().year(-12).format('YYYY'), '-0012', 'YYYY with negative year'); + assert.equal(moment.utc().year(-123).format('YY'), '-23', 'YY with negative year'); + assert.equal(moment.utc().year(-123).format('YYYY'), '-0123', 'YYYY with negative year'); + assert.equal(moment.utc().year(-1234).format('YY'), '-34', 'YY with negative year'); + assert.equal(moment.utc().year(-1234).format('YYYY'), '-1234', 'YYYY with negative year'); + assert.equal(moment.utc().year(-12345).format('YY'), '-45', 'YY with negative year'); + assert.equal(moment.utc().year(-12345).format('YYYY'), '-12345', 'YYYY with negative year'); + }); + + test('format milliseconds', function (assert) { + var b = moment(new Date(2009, 1, 14, 15, 25, 50, 123)); + assert.equal(b.format('S'), '1', 'Deciseconds'); + assert.equal(b.format('SS'), '12', 'Centiseconds'); + assert.equal(b.format('SSS'), '123', 'Milliseconds'); + b.milliseconds(789); + assert.equal(b.format('S'), '7', 'Deciseconds'); + assert.equal(b.format('SS'), '78', 'Centiseconds'); + assert.equal(b.format('SSS'), '789', 'Milliseconds'); + }); + + test('format timezone', function (assert) { + var b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)); + assert.ok(b.format('Z').match(/^[\+\-]\d\d:\d\d$/), b.format('Z') + ' should be something like \'+07:30\''); + assert.ok(b.format('ZZ').match(/^[\+\-]\d{4}$/), b.format('ZZ') + ' should be something like \'+0700\''); + }); + + test('format multiple with utc offset', function (assert) { + var b = moment('2012-10-08 -1200', ['YYYY-MM-DD HH:mm ZZ', 'YYYY-MM-DD ZZ', 'YYYY-MM-DD']); + assert.equal(b.format('YYYY-MM'), '2012-10', 'Parsing multiple formats should not crash with different sized formats'); + }); + + test('isDST', function (assert) { + 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) { + assert.ok(0, 'January and July cannot both be in DST'); + assert.ok(0, 'January and July cannot both be in DST'); + } else if (janIsDst) { + assert.ok(jan1.isDST(), 'January 1 is DST'); + assert.ok(!jul1.isDST(), 'July 1 is not DST'); + } else if (julIsDst) { + assert.ok(!jan1.isDST(), 'January 1 is not DST'); + assert.ok(jul1.isDST(), 'July 1 is DST'); + } else { + assert.ok(!jan1.isDST(), 'January 1 is not DST'); + assert.ok(!jul1.isDST(), 'July 1 is not DST'); + } + }); + + test('unix timestamp', function (assert) { + var m = moment('1234567890.123', 'X'); + assert.equal(m.format('X'), '1234567890', 'unix timestamp without milliseconds'); + assert.equal(m.format('X.S'), '1234567890.1', 'unix timestamp with deciseconds'); + assert.equal(m.format('X.SS'), '1234567890.12', 'unix timestamp with centiseconds'); + assert.equal(m.format('X.SSS'), '1234567890.123', 'unix timestamp with milliseconds'); + + m = moment(1234567890.123, 'X'); + assert.equal(m.format('X'), '1234567890', 'unix timestamp as integer'); + }); + + test('unix offset milliseconds', function (assert) { + var m = moment('1234567890123', 'x'); + assert.equal(m.format('x'), '1234567890123', 'unix offset in milliseconds'); + + m = moment(1234567890123, 'x'); + assert.equal(m.format('x'), '1234567890123', 'unix offset in milliseconds as integer'); + }); + + test('utcOffset sanity checks', function (assert) { + assert.equal(moment().utcOffset() % 15, 0, + 'utc offset should be a multiple of 15 (was ' + moment().utcOffset() + ')'); + + assert.equal(moment().utcOffset(), -(new Date()).getTimezoneOffset(), + 'utcOffset should return the opposite of getTimezoneOffset'); + }); + + test('default format', function (assert) { + var isoRegex = /\d{4}.\d\d.\d\dT\d\d.\d\d.\d\d[\+\-]\d\d:\d\d/; + assert.ok(isoRegex.exec(moment().format()), 'default format (' + moment().format() + ') should match ISO'); + }); + + test('toJSON', function (assert) { + var supportsJson = typeof JSON !== 'undefined' && JSON.stringify && JSON.stringify.call, + date = moment('2012-10-09T21:30:40.678+0100'); + + assert.equal(date.toJSON(), '2012-10-09T20:30:40.678Z', 'should output ISO8601 on moment.fn.toJSON'); + + if (supportsJson) { + assert.equal(JSON.stringify({ + date : date + }), '{"date":"2012-10-09T20:30:40.678Z"}', 'should output ISO8601 on JSON.stringify'); + } + }); + + test('toISOString', function (assert) { + var date = moment.utc('2012-10-09T20:30:40.678'); + + assert.equal(date.toISOString(), '2012-10-09T20:30:40.678Z', 'should output ISO8601 on moment.fn.toISOString'); + + // big years + date = moment.utc('+020123-10-09T20:30:40.678'); + assert.equal(date.toISOString(), '+020123-10-09T20:30:40.678Z', 'ISO8601 format on big positive year'); + // negative years + date = moment.utc('-000001-10-09T20:30:40.678'); + assert.equal(date.toISOString(), '-000001-10-09T20:30:40.678Z', 'ISO8601 format on negative year'); + // big negative years + date = moment.utc('-020123-10-09T20:30:40.678'); + assert.equal(date.toISOString(), '-020123-10-09T20:30:40.678Z', 'ISO8601 format on big negative year'); + }); + + test('long years', function (assert) { + assert.equal(moment.utc().year(2).format('YYYYYY'), '+000002', 'small year with YYYYYY'); + assert.equal(moment.utc().year(2012).format('YYYYYY'), '+002012', 'regular year with YYYYYY'); + assert.equal(moment.utc().year(20123).format('YYYYYY'), '+020123', 'big year with YYYYYY'); + + assert.equal(moment.utc().year(-1).format('YYYYYY'), '-000001', 'small negative year with YYYYYY'); + assert.equal(moment.utc().year(-2012).format('YYYYYY'), '-002012', 'negative year with YYYYYY'); + assert.equal(moment.utc().year(-20123).format('YYYYYY'), '-020123', 'big negative year with YYYYYY'); + }); + + test('iso week formats', function (assert) { + // 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', + '404-12-31': '0404-53', + '405-12-31': '0405-52' + }, i, isoWeek, formatted2, formatted1; + + for (i in cases) { + isoWeek = cases[i].split('-').pop(); + formatted2 = moment(i, 'YYYY-MM-DD').format('WW'); + assert.equal(isoWeek, formatted2, i + ': WW should be ' + isoWeek + ', but ' + formatted2); + isoWeek = isoWeek.replace(/^0+/, ''); + formatted1 = moment(i, 'YYYY-MM-DD').format('W'); + assert.equal(isoWeek, formatted1, i + ': W should be ' + isoWeek + ', but ' + formatted1); + } + }); + + test('iso week year formats', function (assert) { + // 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', + '404-12-31': '0404-53', + '405-12-31': '0405-52' + }, i, isoWeekYear, formatted5, formatted4, formatted2; + + for (i in cases) { + isoWeekYear = cases[i].split('-')[0]; + formatted5 = moment(i, 'YYYY-MM-DD').format('GGGGG'); + assert.equal('0' + isoWeekYear, formatted5, i + ': GGGGG should be ' + isoWeekYear + ', but ' + formatted5); + formatted4 = moment(i, 'YYYY-MM-DD').format('GGGG'); + assert.equal(isoWeekYear, formatted4, i + ': GGGG should be ' + isoWeekYear + ', but ' + formatted4); + formatted2 = moment(i, 'YYYY-MM-DD').format('GG'); + assert.equal(isoWeekYear.slice(2, 4), formatted2, i + ': GG should be ' + isoWeekYear + ', but ' + formatted2); + } + }); + + test('week year formats', function (assert) { + // 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', + '404-12-31': '0404-53', + '405-12-31': '0405-52' + }, i, isoWeekYear, formatted5, formatted4, formatted2; + + moment.locale('dow:1,doy:4', {week: {dow: 1, doy: 4}}); + + for (i in cases) { + isoWeekYear = cases[i].split('-')[0]; + formatted5 = moment(i, 'YYYY-MM-DD').format('ggggg'); + assert.equal('0' + isoWeekYear, formatted5, i + ': ggggg should be ' + isoWeekYear + ', but ' + formatted5); + formatted4 = moment(i, 'YYYY-MM-DD').format('gggg'); + assert.equal(isoWeekYear, formatted4, i + ': gggg should be ' + isoWeekYear + ', but ' + formatted4); + formatted2 = moment(i, 'YYYY-MM-DD').format('gg'); + assert.equal(isoWeekYear.slice(2, 4), formatted2, i + ': gg should be ' + isoWeekYear + ', but ' + formatted2); + } + }); + + test('iso weekday formats', function (assert) { + assert.equal(moment([1985, 1, 4]).format('E'), '1', 'Feb 4 1985 is Monday -- 1st day'); + assert.equal(moment([2029, 8, 18]).format('E'), '2', 'Sep 18 2029 is Tuesday -- 2nd day'); + assert.equal(moment([2013, 3, 24]).format('E'), '3', 'Apr 24 2013 is Wednesday -- 3rd day'); + assert.equal(moment([2015, 2, 5]).format('E'), '4', 'Mar 5 2015 is Thursday -- 4th day'); + assert.equal(moment([1970, 0, 2]).format('E'), '5', 'Jan 2 1970 is Friday -- 5th day'); + assert.equal(moment([2001, 4, 12]).format('E'), '6', 'May 12 2001 is Saturday -- 6th day'); + assert.equal(moment([2000, 0, 2]).format('E'), '7', 'Jan 2 2000 is Sunday -- 7th day'); + }); + + test('weekday formats', function (assert) { + moment.locale('dow: 3,doy: 5', {week: {dow: 3, doy: 5}}); + assert.equal(moment([1985, 1, 6]).format('e'), '0', 'Feb 6 1985 is Wednesday -- 0th day'); + assert.equal(moment([2029, 8, 20]).format('e'), '1', 'Sep 20 2029 is Thursday -- 1st day'); + assert.equal(moment([2013, 3, 26]).format('e'), '2', 'Apr 26 2013 is Friday -- 2nd day'); + assert.equal(moment([2015, 2, 7]).format('e'), '3', 'Mar 7 2015 is Saturday -- 3nd day'); + assert.equal(moment([1970, 0, 4]).format('e'), '4', 'Jan 4 1970 is Sunday -- 4th day'); + assert.equal(moment([2001, 4, 14]).format('e'), '5', 'May 14 2001 is Monday -- 5th day'); + assert.equal(moment([2000, 0, 4]).format('e'), '6', 'Jan 4 2000 is Tuesday -- 6th day'); + }); + + test('toString is just human readable format', function (assert) { + var b = moment(new Date(2009, 1, 5, 15, 25, 50, 125)); + assert.equal(b.toString(), b.format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ')); + }); + + test('toJSON skips postformat', function (assert) { + moment.locale('postformat', { + postformat: function (s) { + s.replace(/./g, 'X'); + } + }); + assert.equal(moment.utc([2000, 0, 1]).toJSON(), '2000-01-01T00:00:00.000Z', 'toJSON doesn\'t postformat'); + moment.locale('postformat', null); + }); + + test('calendar day timezone', function (assert) { + moment.locale('en'); + var zones = [60, -60, 90, -90, 360, -360, 720, -720], + b = moment().utc().startOf('day').subtract({m : 1}), + c = moment().local().startOf('day').subtract({m : 1}), + d = moment().local().startOf('day').subtract({d : 2}), + i, z, a; + + for (i = 0; i < zones.length; ++i) { + z = zones[i]; + a = moment().utcOffset(z).startOf('day').subtract({m: 1}); + assert.equal(moment(a).utcOffset(z).calendar(), 'Yesterday at 11:59 PM', + 'Yesterday at 11:59 PM, not Today, or the wrong time, tz = ' + z); + } + + assert.equal(moment(b).utc().calendar(), 'Yesterday at 11:59 PM', 'Yesterday at 11:59 PM, not Today, or the wrong time'); + assert.equal(moment(c).local().calendar(), 'Yesterday at 11:59 PM', 'Yesterday at 11:59 PM, not Today, or the wrong time'); + assert.equal(moment(c).local().calendar(d), 'Tomorrow at 11:59 PM', 'Tomorrow at 11:59 PM, not Yesterday, or the wrong time'); + }); + + test('invalid', function (assert) { + assert.equal(moment.invalid().format(), 'Invalid date'); + assert.equal(moment.invalid().format('YYYY-MM-DD'), 'Invalid date'); + }); + + test('quarter formats', function (assert) { + assert.equal(moment([1985, 1, 4]).format('Q'), '1', 'Feb 4 1985 is Q1'); + assert.equal(moment([2029, 8, 18]).format('Q'), '3', 'Sep 18 2029 is Q3'); + assert.equal(moment([2013, 3, 24]).format('Q'), '2', 'Apr 24 2013 is Q2'); + assert.equal(moment([2015, 2, 5]).format('Q'), '1', 'Mar 5 2015 is Q1'); + assert.equal(moment([1970, 0, 2]).format('Q'), '1', 'Jan 2 1970 is Q1'); + assert.equal(moment([2001, 11, 12]).format('Q'), '4', 'Dec 12 2001 is Q4'); + assert.equal(moment([2000, 0, 2]).format('[Q]Q-YYYY'), 'Q1-2000', 'Jan 2 2000 is Q1'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('from_to'); + + test('from', function (assert) { + var start = moment(); + moment.locale('en'); + assert.equal(start.from(start.clone().add(5, 'seconds')), 'a few seconds ago', '5 seconds = a few seconds ago'); + assert.equal(start.from(start.clone().add(1, 'minute')), 'a minute ago', '1 minute = a minute ago'); + assert.equal(start.from(start.clone().add(5, 'minutes')), '5 minutes ago', '5 minutes = 5 minutes ago'); + + assert.equal(start.from(start.clone().subtract(5, 'seconds')), 'in a few seconds', '5 seconds = in a few seconds'); + assert.equal(start.from(start.clone().subtract(1, 'minute')), 'in a minute', '1 minute = in a minute'); + assert.equal(start.from(start.clone().subtract(5, 'minutes')), 'in 5 minutes', '5 minutes = in 5 minutes'); + }); + + test('from with absolute duration', function (assert) { + var start = moment(); + moment.locale('en'); + assert.equal(start.from(start.clone().add(5, 'seconds'), true), 'a few seconds', '5 seconds = a few seconds'); + assert.equal(start.from(start.clone().add(1, 'minute'), true), 'a minute', '1 minute = a minute'); + assert.equal(start.from(start.clone().add(5, 'minutes'), true), '5 minutes', '5 minutes = 5 minutes'); + + assert.equal(start.from(start.clone().subtract(5, 'seconds'), true), 'a few seconds', '5 seconds = a few seconds'); + assert.equal(start.from(start.clone().subtract(1, 'minute'), true), 'a minute', '1 minute = a minute'); + assert.equal(start.from(start.clone().subtract(5, 'minutes'), true), '5 minutes', '5 minutes = 5 minutes'); + }); + + test('to', function (assert) { + var start = moment(); + moment.locale('en'); + assert.equal(start.to(start.clone().subtract(5, 'seconds')), 'a few seconds ago', '5 seconds = a few seconds ago'); + assert.equal(start.to(start.clone().subtract(1, 'minute')), 'a minute ago', '1 minute = a minute ago'); + assert.equal(start.to(start.clone().subtract(5, 'minutes')), '5 minutes ago', '5 minutes = 5 minutes ago'); + + assert.equal(start.to(start.clone().add(5, 'seconds')), 'in a few seconds', '5 seconds = in a few seconds'); + assert.equal(start.to(start.clone().add(1, 'minute')), 'in a minute', '1 minute = in a minute'); + assert.equal(start.to(start.clone().add(5, 'minutes')), 'in 5 minutes', '5 minutes = in 5 minutes'); + }); + + test('to with absolute duration', function (assert) { + var start = moment(); + moment.locale('en'); + assert.equal(start.to(start.clone().add(5, 'seconds'), true), 'a few seconds', '5 seconds = a few seconds'); + assert.equal(start.to(start.clone().add(1, 'minute'), true), 'a minute', '1 minute = a minute'); + assert.equal(start.to(start.clone().add(5, 'minutes'), true), '5 minutes', '5 minutes = 5 minutes'); + + assert.equal(start.to(start.clone().subtract(5, 'seconds'), true), 'a few seconds', '5 seconds = a few seconds'); + assert.equal(start.to(start.clone().subtract(1, 'minute'), true), 'a minute', '1 minute = a minute'); + assert.equal(start.to(start.clone().subtract(5, 'minutes'), true), '5 minutes', '5 minutes = 5 minutes'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('getters and setters'); + + test('getters', function (assert) { + var a = moment([2011, 9, 12, 6, 7, 8, 9]); + assert.equal(a.year(), 2011, 'year'); + assert.equal(a.month(), 9, 'month'); + assert.equal(a.date(), 12, 'date'); + assert.equal(a.day(), 3, 'day'); + assert.equal(a.hours(), 6, 'hour'); + assert.equal(a.minutes(), 7, 'minute'); + assert.equal(a.seconds(), 8, 'second'); + assert.equal(a.milliseconds(), 9, 'milliseconds'); + }); + + test('getters programmatic', function (assert) { + var a = moment([2011, 9, 12, 6, 7, 8, 9]); + assert.equal(a.get('year'), 2011, 'year'); + assert.equal(a.get('month'), 9, 'month'); + assert.equal(a.get('date'), 12, 'date'); + assert.equal(a.get('day'), 3, 'day'); + assert.equal(a.get('hour'), 6, 'hour'); + assert.equal(a.get('minute'), 7, 'minute'); + assert.equal(a.get('second'), 8, 'second'); + assert.equal(a.get('milliseconds'), 9, 'milliseconds'); + + //actual getters tested elsewhere + assert.equal(a.get('weekday'), a.weekday(), 'weekday'); + assert.equal(a.get('isoWeekday'), a.isoWeekday(), 'isoWeekday'); + assert.equal(a.get('week'), a.week(), 'week'); + assert.equal(a.get('isoWeek'), a.isoWeek(), 'isoWeek'); + assert.equal(a.get('dayOfYear'), a.dayOfYear(), 'dayOfYear'); + }); + + test('setters plural', function (assert) { + var a = moment(); + a.years(2011); + a.months(9); + a.dates(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(9); + assert.equal(a.years(), 2011, 'years'); + assert.equal(a.months(), 9, 'months'); + assert.equal(a.dates(), 12, 'dates'); + assert.equal(a.days(), 3, 'days'); + assert.equal(a.hours(), 6, 'hours'); + assert.equal(a.minutes(), 7, 'minutes'); + assert.equal(a.seconds(), 8, 'seconds'); + assert.equal(a.milliseconds(), 9, 'milliseconds'); + }); + + test('setters singular', function (assert) { + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hour(6); + a.minute(7); + a.second(8); + a.millisecond(9); + assert.equal(a.year(), 2011, 'year'); + assert.equal(a.month(), 9, 'month'); + assert.equal(a.date(), 12, 'date'); + assert.equal(a.day(), 3, 'day'); + assert.equal(a.hour(), 6, 'hour'); + assert.equal(a.minute(), 7, 'minute'); + assert.equal(a.second(), 8, 'second'); + assert.equal(a.millisecond(), 9, 'milliseconds'); + }); + + test('setters', function (assert) { + var a = moment(); + a.year(2011); + a.month(9); + a.date(12); + a.hours(6); + a.minutes(7); + a.seconds(8); + a.milliseconds(9); + assert.equal(a.year(), 2011, 'year'); + assert.equal(a.month(), 9, 'month'); + assert.equal(a.date(), 12, 'date'); + assert.equal(a.day(), 3, 'day'); + assert.equal(a.hours(), 6, 'hour'); + assert.equal(a.minutes(), 7, 'minute'); + assert.equal(a.seconds(), 8, 'second'); + assert.equal(a.milliseconds(), 9, 'milliseconds'); + + // Test month() behavior. See https://github.com/timrwood/moment/pull/822 + a = moment('20130531', 'YYYYMMDD'); + a.month(3); + assert.equal(a.month(), 3, 'month edge case'); + }); + + test('setter programmatic', function (assert) { + var a = moment(); + a.set('year', 2011); + a.set('month', 9); + a.set('date', 12); + a.set('hours', 6); + a.set('minutes', 7); + a.set('seconds', 8); + a.set('milliseconds', 9); + assert.equal(a.year(), 2011, 'year'); + assert.equal(a.month(), 9, 'month'); + assert.equal(a.date(), 12, 'date'); + assert.equal(a.day(), 3, 'day'); + assert.equal(a.hours(), 6, 'hour'); + assert.equal(a.minutes(), 7, 'minute'); + assert.equal(a.seconds(), 8, 'second'); + assert.equal(a.milliseconds(), 9, 'milliseconds'); + + // Test month() behavior. See https://github.com/timrwood/moment/pull/822 + a = moment('20130531', 'YYYYMMDD'); + a.month(3); + assert.equal(a.month(), 3, 'month edge case'); + }); + + // Disable this, until we weekYear setter is fixed. + // https://github.com/moment/moment/issues/1379 + // test('setters programatic with weeks', function (assert) { + // var a = moment(); + // a.set('weekYear', 2001); + // a.set('week', 49); + // a.set('day', 4); + // assert.equals(a.weekYear(), 2001); + // assert.equals(a.week(), 49); + // assert.equals(a.day(), 4); + + // a.set('weekday', 1); + // assert.equals(a.weekday(), 1); + + // assert.done(); + //}, + + // I think this suffers from the same issue as the non-iso version. + // test('setters programatic with weeks ISO', function (assert) { + // var a = moment(); + // a.set('isoWeekYear', 2001); + // a.set('isoWeek', 49); + // a.set('isoWeekday', 4); + + // assert.equals(a.weekYear(), 2001); + // assert.equals(a.week(), 49); + // assert.equals(a.day(), 4); + + // assert.done(); + //}, + + test('setters strings', function (assert) { + var a = moment([2012]).locale('en'); + assert.equal(a.clone().day(0).day('Wednesday').day(), 3, 'day full name'); + assert.equal(a.clone().day(0).day('Wed').day(), 3, 'day short name'); + assert.equal(a.clone().day(0).day('We').day(), 3, 'day minimal name'); + assert.equal(a.clone().day(0).day('invalid').day(), 0, 'invalid day name'); + assert.equal(a.clone().month(0).month('April').month(), 3, 'month full name'); + assert.equal(a.clone().month(0).month('Apr').month(), 3, 'month short name'); + assert.equal(a.clone().month(0).month('invalid').month(), 0, 'invalid month name'); + }); + + test('setters - falsey values', function (assert) { + var a = moment(); + // ensure minutes wasn't coincidentally 0 already + a.minutes(1); + a.minutes(0); + assert.equal(a.minutes(), 0, 'falsey value'); + }); + + test('chaining setters', function (assert) { + var a = moment(); + a.year(2011) + .month(9) + .date(12) + .hours(6) + .minutes(7) + .seconds(8); + assert.equal(a.year(), 2011, 'year'); + assert.equal(a.month(), 9, 'month'); + assert.equal(a.date(), 12, 'date'); + assert.equal(a.day(), 3, 'day'); + assert.equal(a.hours(), 6, 'hour'); + assert.equal(a.minutes(), 7, 'minute'); + assert.equal(a.seconds(), 8, 'second'); + }); + + test('setter with multiple unit values', function (assert) { + var a = moment(); + a.set({ + year: 2011, + month: 9, + date: 12, + hours: 6, + minutes: 7, + seconds: 8, + milliseconds: 9 + }); + assert.equal(a.year(), 2011, 'year'); + assert.equal(a.month(), 9, 'month'); + assert.equal(a.date(), 12, 'date'); + assert.equal(a.day(), 3, 'day'); + assert.equal(a.hours(), 6, 'hour'); + assert.equal(a.minutes(), 7, 'minute'); + assert.equal(a.seconds(), 8, 'second'); + assert.equal(a.milliseconds(), 9, 'milliseconds'); + }); + + test('day setter', function (assert) { + var a = moment([2011, 0, 15]); + assert.equal(moment(a).day(0).date(), 9, 'set from saturday to sunday'); + assert.equal(moment(a).day(6).date(), 15, 'set from saturday to saturday'); + assert.equal(moment(a).day(3).date(), 12, 'set from saturday to wednesday'); + + a = moment([2011, 0, 9]); + assert.equal(moment(a).day(0).date(), 9, 'set from sunday to sunday'); + assert.equal(moment(a).day(6).date(), 15, 'set from sunday to saturday'); + assert.equal(moment(a).day(3).date(), 12, 'set from sunday to wednesday'); + + a = moment([2011, 0, 12]); + assert.equal(moment(a).day(0).date(), 9, 'set from wednesday to sunday'); + assert.equal(moment(a).day(6).date(), 15, 'set from wednesday to saturday'); + assert.equal(moment(a).day(3).date(), 12, 'set from wednesday to wednesday'); + + assert.equal(moment(a).day(-7).date(), 2, 'set from wednesday to last sunday'); + assert.equal(moment(a).day(-1).date(), 8, 'set from wednesday to last saturday'); + assert.equal(moment(a).day(-4).date(), 5, 'set from wednesday to last wednesday'); + + assert.equal(moment(a).day(7).date(), 16, 'set from wednesday to next sunday'); + assert.equal(moment(a).day(13).date(), 22, 'set from wednesday to next saturday'); + assert.equal(moment(a).day(10).date(), 19, 'set from wednesday to next wednesday'); + + assert.equal(moment(a).day(14).date(), 23, 'set from wednesday to second next sunday'); + assert.equal(moment(a).day(20).date(), 29, 'set from wednesday to second next saturday'); + assert.equal(moment(a).day(17).date(), 26, 'set from wednesday to second next wednesday'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('invalid'); + + test('invalid', function (assert) { + var m = moment.invalid(); + assert.equal(m.isValid(), false); + assert.equal(m.parsingFlags().userInvalidated, true); + assert.ok(isNaN(m.valueOf())); + }); + + test('invalid with existing flag', function (assert) { + var m = moment.invalid({invalidMonth : 'whatchamacallit'}); + assert.equal(m.isValid(), false); + assert.equal(m.parsingFlags().userInvalidated, false); + assert.equal(m.parsingFlags().invalidMonth, 'whatchamacallit'); + assert.ok(isNaN(m.valueOf())); + }); + + test('invalid with custom flag', function (assert) { + var m = moment.invalid({tooBusyWith : 'reiculating splines'}); + assert.equal(m.isValid(), false); + assert.equal(m.parsingFlags().userInvalidated, false); + assert.equal(m.parsingFlags().tooBusyWith, 'reiculating splines'); + assert.ok(isNaN(m.valueOf())); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('is after'); + + test('is after without units', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + assert.equal(m.isAfter(moment(new Date(2012, 3, 2, 3, 5, 5, 10))), false, 'year is later'); + assert.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 3, 5, 10))), true, 'year is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 4, 2, 3, 4, 5, 10))), false, 'month is later'); + assert.equal(m.isAfter(moment(new Date(2011, 2, 2, 3, 4, 5, 10))), true, 'month is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 3, 3, 4, 5, 10))), false, 'day is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 1, 3, 4, 5, 10))), true, 'day is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 4, 4, 5, 10))), false, 'hour is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 2, 4, 5, 10))), true, 'hour is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 5, 5, 10))), false, 'minute is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 3, 5, 10))), true, 'minute is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 6, 10))), false, 'second is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 4, 11))), true, 'second is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 10))), false, 'millisecond match'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 11))), false, 'millisecond is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 9))), true, 'millisecond is earlier'); + assert.equal(m.isAfter(m), false, 'moments are not after themselves'); + assert.equal(+m, +mCopy, 'isAfter second should not change moment'); + }); + + test('is after year', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isAfter(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'year'), false, 'year match'); + assert.equal(m.isAfter(moment(new Date(2010, 5, 6, 7, 8, 9, 10)), 'years'), true, 'plural should work'); + assert.equal(m.isAfter(moment(new Date(2013, 5, 6, 7, 8, 9, 10)), 'year'), false, 'year is later'); + assert.equal(m.isAfter(moment(new Date(2010, 5, 6, 7, 8, 9, 10)), 'year'), true, 'year is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 0, 1, 0, 0, 0, 0)), 'year'), false, 'exact start of year'); + assert.equal(m.isAfter(moment(new Date(2011, 11, 31, 23, 59, 59, 999)), 'year'), false, 'exact end of year'); + assert.equal(m.isAfter(moment(new Date(2012, 0, 1, 0, 0, 0, 0)), 'year'), false, 'start of next year'); + assert.equal(m.isAfter(moment(new Date(2010, 11, 31, 23, 59, 59, 999)), 'year'), true, 'end of previous year'); + assert.equal(m.isAfter(moment(new Date(1980, 11, 31, 23, 59, 59, 999)), 'year'), true, 'end of year far before'); + assert.equal(m.isAfter(m, 'year'), false, 'same moments are not after the same year'); + assert.equal(+m, +mCopy, 'isAfter year should not change moment'); + }); + + test('is after month', function (assert) { + var m = moment(new Date(2011, 2, 3, 4, 5, 6, 7)), mCopy = moment(m); + assert.equal(m.isAfter(moment(new Date(2011, 2, 6, 7, 8, 9, 10)), 'month'), false, 'month match'); + assert.equal(m.isAfter(moment(new Date(2010, 2, 6, 7, 8, 9, 10)), 'months'), true, 'plural should work'); + assert.equal(m.isAfter(moment(new Date(2012, 2, 6, 7, 8, 9, 10)), 'month'), false, 'year is later'); + assert.equal(m.isAfter(moment(new Date(2010, 2, 6, 7, 8, 9, 10)), 'month'), true, 'year is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'month'), false, 'month is later'); + assert.equal(m.isAfter(moment(new Date(2011, 1, 6, 7, 8, 9, 10)), 'month'), true, 'month is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 2, 1, 0, 0, 0, 0)), 'month'), false, 'exact start of month'); + assert.equal(m.isAfter(moment(new Date(2011, 2, 31, 23, 59, 59, 999)), 'month'), false, 'exact end of month'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 1, 0, 0, 0, 0)), 'month'), false, 'start of next month'); + assert.equal(m.isAfter(moment(new Date(2011, 1, 27, 23, 59, 59, 999)), 'month'), true, 'end of previous month'); + assert.equal(m.isAfter(moment(new Date(2010, 12, 31, 23, 59, 59, 999)), 'month'), true, 'later month but earlier year'); + assert.equal(m.isAfter(m, 'month'), false, 'same moments are not after the same month'); + assert.equal(+m, +mCopy, 'isAfter month should not change moment'); + }); + + test('is after day', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 7, 8, 9, 10)), 'day'), false, 'day match'); + assert.equal(m.isAfter(moment(new Date(2010, 3, 2, 7, 8, 9, 10)), 'days'), true, 'plural should work'); + assert.equal(m.isAfter(moment(new Date(2012, 3, 2, 7, 8, 9, 10)), 'day'), false, 'year is later'); + assert.equal(m.isAfter(moment(new Date(2010, 3, 2, 7, 8, 9, 10)), 'day'), true, 'year is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 4, 2, 7, 8, 9, 10)), 'day'), false, 'month is later'); + assert.equal(m.isAfter(moment(new Date(2011, 2, 2, 7, 8, 9, 10)), 'day'), true, 'month is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 3, 7, 8, 9, 10)), 'day'), false, 'day is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 1, 7, 8, 9, 10)), 'day'), true, 'day is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 0, 0, 0, 0)), 'day'), false, 'exact start of day'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 23, 59, 59, 999)), 'day'), false, 'exact end of day'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 3, 0, 0, 0, 0)), 'day'), false, 'start of next day'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 1, 23, 59, 59, 999)), 'day'), true, 'end of previous day'); + assert.equal(m.isAfter(moment(new Date(2010, 3, 10, 0, 0, 0, 0)), 'day'), true, 'later day but earlier year'); + assert.equal(m.isAfter(m, 'day'), false, 'same moments are not after the same day'); + assert.equal(+m, +mCopy, 'isAfter day should not change moment'); + }); + + test('is after hour', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 8, 9, 10)), 'hour'), false, 'hour match'); + assert.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 8, 9, 10)), 'hours'), true, 'plural should work'); + assert.equal(m.isAfter(moment(new Date(2012, 3, 2, 3, 8, 9, 10)), 'hour'), false, 'year is later'); + assert.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 8, 9, 10)), 'hour'), true, 'year is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 4, 2, 3, 8, 9, 10)), 'hour'), false, 'month is later'); + assert.equal(m.isAfter(moment(new Date(2011, 1, 2, 3, 8, 9, 10)), 'hour'), true, 'month is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 3, 3, 8, 9, 10)), 'hour'), false, 'day is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 1, 3, 8, 9, 10)), 'hour'), true, 'day is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 4, 8, 9, 10)), 'hour'), false, 'hour is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 8, 9, 10)), 'hour'), false, 'hour is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 0, 0, 0)), 'hour'), false, 'exact start of hour'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 59, 59, 999)), 'hour'), false, 'exact end of hour'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 4, 0, 0, 0)), 'hour'), false, 'start of next hour'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 2, 59, 59, 999)), 'hour'), true, 'end of previous hour'); + assert.equal(m.isAfter(m, 'hour'), false, 'same moments are not after the same hour'); + assert.equal(+m, +mCopy, 'isAfter hour should not change moment'); + }); + + test('is after minute', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 9, 10)), 'minute'), false, 'minute match'); + assert.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 4, 9, 10)), 'minutes'), true, 'plural should work'); + assert.equal(m.isAfter(moment(new Date(2012, 3, 2, 3, 4, 9, 10)), 'minute'), false, 'year is later'); + assert.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 4, 9, 10)), 'minute'), true, 'year is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 4, 2, 3, 4, 9, 10)), 'minute'), false, 'month is later'); + assert.equal(m.isAfter(moment(new Date(2011, 2, 2, 3, 4, 9, 10)), 'minute'), true, 'month is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 3, 3, 4, 9, 10)), 'minute'), false, 'day is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 1, 3, 4, 9, 10)), 'minute'), true, 'day is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 4, 4, 9, 10)), 'minute'), false, 'hour is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 2, 4, 9, 10)), 'minute'), true, 'hour is earler'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 5, 9, 10)), 'minute'), false, 'minute is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 3, 9, 10)), 'minute'), true, 'minute is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 0, 0)), 'minute'), false, 'exact start of minute'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 59, 999)), 'minute'), false, 'exact end of minute'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 5, 0, 0)), 'minute'), false, 'start of next minute'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 3, 59, 999)), 'minute'), true, 'end of previous minute'); + assert.equal(m.isAfter(m, 'minute'), false, 'same moments are not after the same minute'); + assert.equal(+m, +mCopy, 'isAfter minute should not change moment'); + }); + + test('is after second', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 10)), 'second'), false, 'second match'); + assert.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'seconds'), true, 'plural should work'); + assert.equal(m.isAfter(moment(new Date(2012, 3, 2, 3, 4, 5, 10)), 'second'), false, 'year is later'); + assert.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'second'), true, 'year is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 4, 2, 3, 4, 5, 10)), 'second'), false, 'month is later'); + assert.equal(m.isAfter(moment(new Date(2011, 2, 2, 3, 4, 5, 10)), 'second'), true, 'month is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 3, 3, 4, 5, 10)), 'second'), false, 'day is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 1, 1, 4, 5, 10)), 'second'), true, 'day is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 4, 4, 5, 10)), 'second'), false, 'hour is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 1, 4, 1, 5, 10)), 'second'), true, 'hour is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 5, 5, 10)), 'second'), false, 'minute is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 3, 5, 10)), 'second'), true, 'minute is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 6, 10)), 'second'), false, 'second is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 4, 5)), 'second'), true, 'second is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 0)), 'second'), false, 'exact start of second'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 999)), 'second'), false, 'exact end of second'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 6, 0)), 'second'), false, 'start of next second'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 4, 999)), 'second'), true, 'end of previous second'); + assert.equal(m.isAfter(m, 'second'), false, 'same moments are not after the same second'); + assert.equal(+m, +mCopy, 'isAfter second should not change moment'); + }); + + test('is after millisecond', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 5, 10)), 'millisecond'), false, 'millisecond match'); + assert.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'milliseconds'), true, 'plural should work'); + assert.equal(m.isAfter(moment(new Date(2012, 3, 2, 3, 4, 5, 10)), 'millisecond'), false, 'year is later'); + assert.equal(m.isAfter(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'millisecond'), true, 'year is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 4, 2, 3, 4, 5, 10)), 'millisecond'), false, 'month is later'); + assert.equal(m.isAfter(moment(new Date(2011, 2, 2, 3, 4, 5, 10)), 'millisecond'), true, 'month is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 3, 3, 4, 5, 10)), 'millisecond'), false, 'day is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 1, 1, 4, 5, 10)), 'millisecond'), true, 'day is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 4, 4, 5, 10)), 'millisecond'), false, 'hour is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 1, 4, 1, 5, 10)), 'millisecond'), true, 'hour is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 5, 5, 10)), 'millisecond'), false, 'minute is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 3, 5, 10)), 'millisecond'), true, 'minute is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 6, 10)), 'millisecond'), false, 'second is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 4, 5)), 'millisecond'), true, 'second is earlier'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 6, 11)), 'millisecond'), false, 'millisecond is later'); + assert.equal(m.isAfter(moment(new Date(2011, 3, 2, 3, 4, 4, 9)), 'millisecond'), true, 'millisecond is earlier'); + assert.equal(m.isAfter(m, 'millisecond'), false, 'same moments are not after the same millisecond'); + assert.equal(+m, +mCopy, 'isAfter millisecond should not change moment'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('is before'); + + test('is after without units', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + assert.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 5, 5, 10))), true, 'year is later'); + assert.equal(m.isBefore(moment(new Date(2010, 3, 2, 3, 3, 5, 10))), false, 'year is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 4, 2, 3, 4, 5, 10))), true, 'month is later'); + assert.equal(m.isBefore(moment(new Date(2011, 2, 2, 3, 4, 5, 10))), false, 'month is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 3, 3, 4, 5, 10))), true, 'day is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 1, 3, 4, 5, 10))), false, 'day is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 4, 4, 5, 10))), true, 'hour is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 2, 4, 5, 10))), false, 'hour is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 5, 5, 10))), true, 'minute is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 3, 5, 10))), false, 'minute is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 6, 10))), true, 'second is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 4, 11))), false, 'second is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 10))), false, 'millisecond match'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 11))), true, 'millisecond is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 9))), false, 'millisecond is earlier'); + assert.equal(m.isBefore(m), false, 'moments are not before themselves'); + assert.equal(+m, +mCopy, 'isBefore second should not change moment'); + }); + + test('is before year', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isBefore(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'year'), false, 'year match'); + assert.equal(m.isBefore(moment(new Date(2012, 5, 6, 7, 8, 9, 10)), 'years'), true, 'plural should work'); + assert.equal(m.isBefore(moment(new Date(2013, 5, 6, 7, 8, 9, 10)), 'year'), true, 'year is later'); + assert.equal(m.isBefore(moment(new Date(2010, 5, 6, 7, 8, 9, 10)), 'year'), false, 'year is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 0, 1, 0, 0, 0, 0)), 'year'), false, 'exact start of year'); + assert.equal(m.isBefore(moment(new Date(2011, 11, 31, 23, 59, 59, 999)), 'year'), false, 'exact end of year'); + assert.equal(m.isBefore(moment(new Date(2012, 0, 1, 0, 0, 0, 0)), 'year'), true, 'start of next year'); + assert.equal(m.isBefore(moment(new Date(2010, 11, 31, 23, 59, 59, 999)), 'year'), false, 'end of previous year'); + assert.equal(m.isBefore(moment(new Date(1980, 11, 31, 23, 59, 59, 999)), 'year'), false, 'end of year far before'); + assert.equal(m.isBefore(m, 'year'), false, 'same moments are not before the same year'); + assert.equal(+m, +mCopy, 'isBefore year should not change moment'); + }); + + test('is before month', function (assert) { + var m = moment(new Date(2011, 2, 3, 4, 5, 6, 7)), mCopy = moment(m); + assert.equal(m.isBefore(moment(new Date(2011, 2, 6, 7, 8, 9, 10)), 'month'), false, 'month match'); + assert.equal(m.isBefore(moment(new Date(2012, 2, 6, 7, 8, 9, 10)), 'months'), true, 'plural should work'); + assert.equal(m.isBefore(moment(new Date(2012, 2, 6, 7, 8, 9, 10)), 'month'), true, 'year is later'); + assert.equal(m.isBefore(moment(new Date(2010, 2, 6, 7, 8, 9, 10)), 'month'), false, 'year is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'month'), true, 'month is later'); + assert.equal(m.isBefore(moment(new Date(2011, 1, 6, 7, 8, 9, 10)), 'month'), false, 'month is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 2, 1, 0, 0, 0, 0)), 'month'), false, 'exact start of month'); + assert.equal(m.isBefore(moment(new Date(2011, 2, 31, 23, 59, 59, 999)), 'month'), false, 'exact end of month'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 1, 0, 0, 0, 0)), 'month'), true, 'start of next month'); + assert.equal(m.isBefore(moment(new Date(2011, 1, 27, 23, 59, 59, 999)), 'month'), false, 'end of previous month'); + assert.equal(m.isBefore(moment(new Date(2010, 12, 31, 23, 59, 59, 999)), 'month'), false, 'later month but earlier year'); + assert.equal(m.isBefore(m, 'month'), false, 'same moments are not before the same month'); + assert.equal(+m, +mCopy, 'isBefore month should not change moment'); + }); + + test('is before day', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 7, 8, 9, 10)), 'day'), false, 'day match'); + assert.equal(m.isBefore(moment(new Date(2012, 3, 2, 7, 8, 9, 10)), 'days'), true, 'plural should work'); + assert.equal(m.isBefore(moment(new Date(2012, 3, 2, 7, 8, 9, 10)), 'day'), true, 'year is later'); + assert.equal(m.isBefore(moment(new Date(2010, 3, 2, 7, 8, 9, 10)), 'day'), false, 'year is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 4, 2, 7, 8, 9, 10)), 'day'), true, 'month is later'); + assert.equal(m.isBefore(moment(new Date(2011, 2, 2, 7, 8, 9, 10)), 'day'), false, 'month is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 3, 7, 8, 9, 10)), 'day'), true, 'day is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 1, 7, 8, 9, 10)), 'day'), false, 'day is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 0, 0, 0, 0)), 'day'), false, 'exact start of day'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 23, 59, 59, 999)), 'day'), false, 'exact end of day'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 3, 0, 0, 0, 0)), 'day'), true, 'start of next day'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 1, 23, 59, 59, 999)), 'day'), false, 'end of previous day'); + assert.equal(m.isBefore(moment(new Date(2010, 3, 10, 0, 0, 0, 0)), 'day'), false, 'later day but earlier year'); + assert.equal(m.isBefore(m, 'day'), false, 'same moments are not before the same day'); + assert.equal(+m, +mCopy, 'isBefore day should not change moment'); + }); + + test('is before hour', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 8, 9, 10)), 'hour'), false, 'hour match'); + assert.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 8, 9, 10)), 'hours'), true, 'plural should work'); + assert.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 8, 9, 10)), 'hour'), true, 'year is later'); + assert.equal(m.isBefore(moment(new Date(2010, 3, 2, 3, 8, 9, 10)), 'hour'), false, 'year is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 4, 2, 3, 8, 9, 10)), 'hour'), true, 'month is later'); + assert.equal(m.isBefore(moment(new Date(2011, 1, 2, 3, 8, 9, 10)), 'hour'), false, 'month is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 3, 3, 8, 9, 10)), 'hour'), true, 'day is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 1, 3, 8, 9, 10)), 'hour'), false, 'day is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 4, 8, 9, 10)), 'hour'), true, 'hour is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 8, 9, 10)), 'hour'), false, 'hour is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 0, 0, 0)), 'hour'), false, 'exact start of hour'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 59, 59, 999)), 'hour'), false, 'exact end of hour'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 4, 0, 0, 0)), 'hour'), true, 'start of next hour'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 2, 59, 59, 999)), 'hour'), false, 'end of previous hour'); + assert.equal(m.isBefore(m, 'hour'), false, 'same moments are not before the same hour'); + assert.equal(+m, +mCopy, 'isBefore hour should not change moment'); + }); + + test('is before minute', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 9, 10)), 'minute'), false, 'minute match'); + assert.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 4, 9, 10)), 'minutes'), true, 'plural should work'); + assert.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 4, 9, 10)), 'minute'), true, 'year is later'); + assert.equal(m.isBefore(moment(new Date(2010, 3, 2, 3, 4, 9, 10)), 'minute'), false, 'year is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 4, 2, 3, 4, 9, 10)), 'minute'), true, 'month is later'); + assert.equal(m.isBefore(moment(new Date(2011, 2, 2, 3, 4, 9, 10)), 'minute'), false, 'month is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 3, 3, 4, 9, 10)), 'minute'), true, 'day is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 1, 3, 4, 9, 10)), 'minute'), false, 'day is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 4, 4, 9, 10)), 'minute'), true, 'hour is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 2, 4, 9, 10)), 'minute'), false, 'hour is earler'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 5, 9, 10)), 'minute'), true, 'minute is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 3, 9, 10)), 'minute'), false, 'minute is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 0, 0)), 'minute'), false, 'exact start of minute'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 59, 999)), 'minute'), false, 'exact end of minute'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 5, 0, 0)), 'minute'), true, 'start of next minute'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 3, 59, 999)), 'minute'), false, 'end of previous minute'); + assert.equal(m.isBefore(m, 'minute'), false, 'same moments are not before the same minute'); + assert.equal(+m, +mCopy, 'isBefore minute should not change moment'); + }); + + test('is before second', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 10)), 'second'), false, 'second match'); + assert.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 4, 5, 10)), 'seconds'), true, 'plural should work'); + assert.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 4, 5, 10)), 'second'), true, 'year is later'); + assert.equal(m.isBefore(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'second'), false, 'year is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 4, 2, 3, 4, 5, 10)), 'second'), true, 'month is later'); + assert.equal(m.isBefore(moment(new Date(2011, 2, 2, 3, 4, 5, 10)), 'second'), false, 'month is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 3, 3, 4, 5, 10)), 'second'), true, 'day is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 1, 1, 4, 5, 10)), 'second'), false, 'day is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 4, 4, 5, 10)), 'second'), true, 'hour is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 1, 4, 1, 5, 10)), 'second'), false, 'hour is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 5, 5, 10)), 'second'), true, 'minute is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 3, 5, 10)), 'second'), false, 'minute is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 6, 10)), 'second'), true, 'second is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 4, 5)), 'second'), false, 'second is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 0)), 'second'), false, 'exact start of second'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 999)), 'second'), false, 'exact end of second'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 6, 0)), 'second'), true, 'start of next second'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 4, 999)), 'second'), false, 'end of previous second'); + assert.equal(m.isBefore(m, 'second'), false, 'same moments are not before the same second'); + assert.equal(+m, +mCopy, 'isBefore second should not change moment'); + }); + + test('is before millisecond', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 5, 10)), 'millisecond'), false, 'millisecond match'); + assert.equal(m.isBefore(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'milliseconds'), false, 'plural should work'); + assert.equal(m.isBefore(moment(new Date(2012, 3, 2, 3, 4, 5, 10)), 'millisecond'), true, 'year is later'); + assert.equal(m.isBefore(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'millisecond'), false, 'year is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 4, 2, 3, 4, 5, 10)), 'millisecond'), true, 'month is later'); + assert.equal(m.isBefore(moment(new Date(2011, 2, 2, 3, 4, 5, 10)), 'millisecond'), false, 'month is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 3, 3, 4, 5, 10)), 'millisecond'), true, 'day is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 1, 1, 4, 5, 10)), 'millisecond'), false, 'day is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 4, 4, 5, 10)), 'millisecond'), true, 'hour is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 1, 4, 1, 5, 10)), 'millisecond'), false, 'hour is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 5, 5, 10)), 'millisecond'), true, 'minute is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 3, 5, 10)), 'millisecond'), false, 'minute is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 6, 10)), 'millisecond'), true, 'second is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 4, 5)), 'millisecond'), false, 'second is earlier'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 6, 11)), 'millisecond'), true, 'millisecond is later'); + assert.equal(m.isBefore(moment(new Date(2011, 3, 2, 3, 4, 4, 9)), 'millisecond'), false, 'millisecond is earlier'); + assert.equal(m.isBefore(m, 'millisecond'), false, 'same moments are not before the same millisecond'); + assert.equal(+m, +mCopy, 'isBefore millisecond should not change moment'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('is between'); + + test('is between without units', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + assert.equal(m.isBetween( + moment(new Date(2009, 3, 2, 3, 4, 5, 10)), + moment(new Date(2011, 3, 2, 3, 4, 5, 10))), false, 'year is later'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 4, 5, 10)), + moment(new Date(2013, 3, 2, 3, 4, 5, 10))), false, 'year is earlier'); + assert.equal(m.isBetween( + moment(new Date(2010, 3, 2, 3, 4, 5, 10)), + moment(new Date(2012, 3, 2, 3, 4, 5, 10))), true, 'year is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 4, 5, 10)), + moment(new Date(2011, 3, 2, 3, 4, 5, 10))), false, 'month is later'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 4, 5, 10)), + moment(new Date(2011, 5, 2, 3, 4, 5, 10))), false, 'month is earlier'); + assert.equal(m.isBetween( + moment(new Date(2011, 2, 2, 3, 4, 5, 10)), + moment(new Date(2011, 4, 2, 3, 4, 5, 10))), true, 'month is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 1, 3, 4, 5, 10)), + moment(new Date(2011, 3, 2, 3, 4, 5, 10))), false, 'day is later'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 4, 5, 10)), + moment(new Date(2011, 3, 4, 3, 4, 5, 10))), false, 'day is earlier'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 1, 3, 4, 5, 10)), + moment(new Date(2011, 3, 3, 3, 4, 5, 10))), true, 'day is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 1, 4, 5, 10)), + moment(new Date(2011, 3, 2, 3, 4, 5, 10))), false, 'hour is later'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 4, 5, 10)), + moment(new Date(2011, 3, 2, 5, 4, 5, 10))), false, 'hour is earlier'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 2, 4, 5, 10)), + moment(new Date(2011, 3, 2, 4, 4, 5, 10))), true, 'hour is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 4, 5, 10)), + moment(new Date(2011, 3, 2, 3, 6, 5, 10))), false, 'minute is later'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 2, 5, 10)), + moment(new Date(2011, 3, 2, 3, 4, 5, 10))), false, 'minute is earlier'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 3, 5, 10)), + moment(new Date(2011, 3, 2, 3, 5, 5, 10))), true, 'minute is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 4, 5, 10)), + moment(new Date(2011, 3, 2, 3, 4, 7, 10))), false, 'second is later'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 4, 3, 10)), + moment(new Date(2011, 3, 2, 3, 4, 5, 10))), false, 'second is earlier'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 4, 4, 10)), + moment(new Date(2011, 3, 2, 3, 4, 6, 10))), true, 'second is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 4, 5, 10)), + moment(new Date(2011, 3, 2, 3, 4, 5, 12))), false, 'millisecond is later'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 4, 5, 8)), + moment(new Date(2011, 3, 2, 3, 4, 5, 10))), false, 'millisecond is earlier'); + assert.equal(m.isBetween( + moment(new Date(2011, 3, 2, 3, 4, 5, 9)), + moment(new Date(2011, 3, 2, 3, 4, 5, 11))), true, 'millisecond is between'); + assert.equal(m.isBetween(m, m), false, 'moments are not between themselves'); + assert.equal(+m, +mCopy, 'isBetween second should not change moment'); + }); + + test('is between year', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isBetween( + moment(new Date(2011, 5, 6, 7, 8, 9, 10)), + moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'year'), false, 'year match'); + assert.equal(m.isBetween( + moment(new Date(2010, 5, 6, 7, 8, 9, 10)), + moment(new Date(2012, 5, 6, 7, 8, 9, 10)), 'years'), true, 'plural should work'); + assert.equal(m.isBetween( + moment(new Date(2010, 5, 6, 7, 8, 9, 10)), + moment(new Date(2012, 5, 6, 7, 8, 9, 10)), 'year'), true, 'year is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 5, 6, 7, 8, 9, 10)), + moment(new Date(2013, 5, 6, 7, 8, 9, 10)), 'year'), false, 'year is earlier'); + assert.equal(m.isBetween( + moment(new Date(2010, 5, 6, 7, 8, 9, 10)), + moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'year'), false, 'year is later'); + assert.equal(m.isBetween(m, 'year'), false, 'same moments are not between the same year'); + assert.equal(+m, +mCopy, 'isBetween year should not change moment'); + }); + + test('is between month', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 6, 7, 8, 9, 10)), + moment(new Date(2011, 1, 6, 7, 8, 9, 10)), 'month'), false, 'month match'); + assert.equal(m.isBetween( + moment(new Date(2011, 0, 6, 7, 8, 9, 10)), + moment(new Date(2011, 2, 6, 7, 8, 9, 10)), 'months'), true, 'plural should work'); + assert.equal(m.isBetween( + moment(new Date(2011, 0, 31, 23, 59, 59, 999)), + moment(new Date(2011, 2, 1, 0, 0, 0, 0)), 'month'), true, 'month is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 6, 7, 8, 9, 10)), + moment(new Date(2011, 2, 6, 7, 8, 9, 10)), 'month'), false, 'month is earlier'); + assert.equal(m.isBetween( + moment(new Date(2011, 11, 6, 7, 8, 9, 10)), + moment(new Date(2011, 1, 6, 7, 8, 9, 10)), 'month'), false, 'month is later'); + assert.equal(m.isBetween(m, 'month'), false, 'same moments are not between the same month'); + assert.equal(+m, +mCopy, 'isBetween month should not change moment'); + }); + + test('is between day', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 7, 8, 9, 10)), + moment(new Date(2011, 1, 2, 7, 8, 9, 10)), 'day'), false, 'day match'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 1, 7, 8, 9, 10)), + moment(new Date(2011, 1, 3, 7, 8, 9, 10)), 'days'), true, 'plural should work'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 1, 7, 8, 9, 10)), + moment(new Date(2011, 1, 3, 7, 8, 9, 10)), 'day'), true, 'day is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 7, 8, 9, 10)), + moment(new Date(2011, 1, 4, 7, 8, 9, 10)), 'day'), false, 'day is earlier'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 1, 7, 8, 9, 10)), + moment(new Date(2011, 1, 2, 7, 8, 9, 10)), 'day'), false, 'day is later'); + assert.equal(m.isBetween(m, 'day'), false, 'same moments are not between the same day'); + assert.equal(+m, +mCopy, 'isBetween day should not change moment'); + }); + + test('is between hour', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 5, 9, 10)), + moment(new Date(2011, 1, 2, 3, 9, 9, 10)), 'hour'), false, 'hour match'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 1, 59, 59, 999)), + moment(new Date(2011, 1, 2, 4, 0, 0, 0)), 'hours'), true, 'plural should work'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 2, 59, 59, 999)), + moment(new Date(2011, 1, 2, 4, 0, 0, 0)), 'hour'), true, 'hour is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 7, 8, 9, 10)), + moment(new Date(2011, 1, 2, 7, 8, 9, 10)), 'hour'), false, 'hour is earlier'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 7, 8, 9, 10)), + moment(new Date(2011, 1, 2, 7, 8, 9, 10)), 'hour'), false, 'hour is later'); + assert.equal(m.isBetween(m, 'hour'), false, 'same moments are not between the same hour'); + assert.equal(+m, +mCopy, 'isBetween hour should not change moment'); + }); + + test('is between minute', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 4, 9, 10)), + moment(new Date(2011, 1, 2, 3, 4, 9, 10)), 'minute'), false, 'minute match'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 3, 9, 10)), + moment(new Date(2011, 1, 2, 3, 5, 9, 10)), 'minutes'), true, 'plural should work'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 3, 59, 999)), + moment(new Date(2011, 1, 2, 3, 5, 0, 0)), 'minute'), true, 'minute is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 5, 0, 0)), + moment(new Date(2011, 1, 2, 3, 8, 9, 10)), 'minute'), false, 'minute is earlier'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 2, 9, 10)), + moment(new Date(2011, 1, 2, 3, 3, 59, 999)), 'minute'), false, 'minute is later'); + assert.equal(m.isBetween(m, 'minute'), false, 'same moments are not between the same minute'); + assert.equal(+m, +mCopy, 'isBetween minute should not change moment'); + }); + + test('is between second', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 4, 5, 10)), + moment(new Date(2011, 1, 2, 3, 4, 5, 10)), 'second'), false, 'second match'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 4, 4, 10)), + moment(new Date(2011, 1, 2, 3, 4, 6, 10)), 'seconds'), true, 'plural should work'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 4, 4, 999)), + moment(new Date(2011, 1, 2, 3, 4, 6, 0)), 'second'), true, 'second is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 4, 6, 0)), + moment(new Date(2011, 1, 2, 3, 4, 7, 10)), 'second'), false, 'second is earlier'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 4, 3, 10)), + moment(new Date(2011, 1, 2, 3, 4, 4, 999)), 'second'), false, 'second is later'); + assert.equal(m.isBetween(m, 'second'), false, 'same moments are not between the same second'); + assert.equal(+m, +mCopy, 'isBetween second should not change moment'); + }); + + test('is between millisecond', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 4, 5, 6)), + moment(new Date(2011, 1, 2, 3, 4, 5, 6)), 'millisecond'), false, 'millisecond match'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 4, 5, 5)), + moment(new Date(2011, 1, 2, 3, 4, 5, 7)), 'milliseconds'), true, 'plural should work'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 4, 5, 5)), + moment(new Date(2011, 1, 2, 3, 4, 5, 7)), 'millisecond'), true, 'millisecond is between'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 4, 5, 7)), + moment(new Date(2011, 1, 2, 3, 4, 5, 10)), 'millisecond'), false, 'millisecond is earlier'); + assert.equal(m.isBetween( + moment(new Date(2011, 1, 2, 3, 4, 5, 4)), + moment(new Date(2011, 1, 2, 3, 4, 5, 6)), 'millisecond'), false, 'millisecond is later'); + assert.equal(m.isBetween(m, 'millisecond'), false, 'same moments are not between the same millisecond'); + assert.equal(+m, +mCopy, 'isBetween millisecond should not change moment'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('is date'); + + test('isDate recognizes Date objects', function (assert) { + assert.ok(moment.isDate(new Date()), 'no args (now)'); + assert.ok(moment.isDate(new Date([2014, 2, 15])), 'array args'); + assert.ok(moment.isDate(new Date('2014-03-15')), 'string args'); + assert.ok(moment.isDate(new Date('does NOT look like a date')), 'invalid date'); + }); + + test('isDate rejects non-Date objects', function (assert) { + assert.ok(!moment.isDate(), 'nothing'); + assert.ok(!moment.isDate(undefined), 'undefined'); + assert.ok(!moment.isDate(null), 'string args'); + assert.ok(!moment.isDate(42), 'number'); + assert.ok(!moment.isDate('2014-03-15'), 'string'); + assert.ok(!moment.isDate([2014, 2, 15]), 'array'); + assert.ok(!moment.isDate({year: 2014, month: 2, day: 15}), 'object'); + assert.ok(!moment.isDate({toString: function () { + return '[object Date]'; + }}), 'lying object'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('is moment'); + + test('is moment object', function (assert) { + var MyObj = function () {}, + extend = function (a, b) { + var i; + for (i in b) { + a[i] = b[i]; + } + return a; + }; + MyObj.prototype.toDate = function () { + return new Date(); + }; + + assert.ok(moment.isMoment(moment()), 'simple moment object'); + assert.ok(moment.isMoment(moment(null)), 'invalid moment object'); + assert.ok(moment.isMoment(extend({}, moment())), 'externally cloned moments are moments'); + assert.ok(moment.isMoment(extend({}, moment.utc())), 'externally cloned utc moments are moments'); + + assert.ok(!moment.isMoment(new MyObj()), 'myObj is not moment object'); + assert.ok(!moment.isMoment(moment), 'moment function is not moment object'); + assert.ok(!moment.isMoment(new Date()), 'date object is not moment object'); + assert.ok(!moment.isMoment(Object), 'Object is not moment object'); + assert.ok(!moment.isMoment('foo'), 'string is not moment object'); + assert.ok(!moment.isMoment(1), 'number is not moment object'); + assert.ok(!moment.isMoment(NaN), 'NaN is not moment object'); + assert.ok(!moment.isMoment(null), 'null is not moment object'); + assert.ok(!moment.isMoment(undefined), 'undefined is not moment object'); + }); + + test('is moment with hacked hasOwnProperty', function (assert) { + var obj = {}; + // HACK to suppress jshint warning about bad property name + obj['hasOwnMoney'.replace('Money', 'Property')] = function () { + return true; + }; + + assert.ok(!moment.isMoment(obj), 'isMoment works even if passed object has a wrong hasOwnProperty implementation (ie8)'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('is same'); + + test('is same without units', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + assert.equal(m.isSame(moment(new Date(2012, 3, 2, 3, 5, 5, 10))), false, 'year is later'); + assert.equal(m.isSame(moment(new Date(2010, 3, 2, 3, 3, 5, 10))), false, 'year is earlier'); + assert.equal(m.isSame(moment(new Date(2011, 4, 2, 3, 4, 5, 10))), false, 'month is later'); + assert.equal(m.isSame(moment(new Date(2011, 2, 2, 3, 4, 5, 10))), false, 'month is earlier'); + assert.equal(m.isSame(moment(new Date(2011, 3, 3, 3, 4, 5, 10))), false, 'day is later'); + assert.equal(m.isSame(moment(new Date(2011, 3, 1, 3, 4, 5, 10))), false, 'day is earlier'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 4, 4, 5, 10))), false, 'hour is later'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 2, 4, 5, 10))), false, 'hour is earlier'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 5, 5, 10))), false, 'minute is later'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 3, 5, 10))), false, 'minute is earlier'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 6, 10))), false, 'second is later'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 4, 11))), false, 'second is earlier'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 5, 10))), true, 'millisecond match'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 5, 11))), false, 'millisecond is later'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 5, 9))), false, 'millisecond is earlier'); + assert.equal(m.isSame(m), true, 'moments are the same as themselves'); + assert.equal(+m, +mCopy, 'isSame second should not change moment'); + }); + + test('is same year', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isSame(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'year'), true, 'year match'); + assert.equal(m.isSame(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'years'), true, 'plural should work'); + assert.equal(m.isSame(moment(new Date(2012, 5, 6, 7, 8, 9, 10)), 'year'), false, 'year mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 0, 1, 0, 0, 0, 0)), 'year'), true, 'exact start of year'); + assert.equal(m.isSame(moment(new Date(2011, 11, 31, 23, 59, 59, 999)), 'year'), true, 'exact end of year'); + assert.equal(m.isSame(moment(new Date(2012, 0, 1, 0, 0, 0, 0)), 'year'), false, 'start of next year'); + assert.equal(m.isSame(moment(new Date(2010, 11, 31, 23, 59, 59, 999)), 'year'), false, 'end of previous year'); + assert.equal(m.isSame(m, 'year'), true, 'same moments are in the same year'); + assert.equal(+m, +mCopy, 'isSame year should not change moment'); + }); + + test('is same month', function (assert) { + var m = moment(new Date(2011, 2, 3, 4, 5, 6, 7)), mCopy = moment(m); + assert.equal(m.isSame(moment(new Date(2011, 2, 6, 7, 8, 9, 10)), 'month'), true, 'month match'); + assert.equal(m.isSame(moment(new Date(2011, 2, 6, 7, 8, 9, 10)), 'months'), true, 'plural should work'); + assert.equal(m.isSame(moment(new Date(2012, 2, 6, 7, 8, 9, 10)), 'month'), false, 'year mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 5, 6, 7, 8, 9, 10)), 'month'), false, 'month mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 2, 1, 0, 0, 0, 0)), 'month'), true, 'exact start of month'); + assert.equal(m.isSame(moment(new Date(2011, 2, 31, 23, 59, 59, 999)), 'month'), true, 'exact end of month'); + assert.equal(m.isSame(moment(new Date(2011, 3, 1, 0, 0, 0, 0)), 'month'), false, 'start of next month'); + assert.equal(m.isSame(moment(new Date(2011, 1, 27, 23, 59, 59, 999)), 'month'), false, 'end of previous month'); + assert.equal(m.isSame(m, 'month'), true, 'same moments are in the same month'); + assert.equal(+m, +mCopy, 'isSame month should not change moment'); + }); + + test('is same day', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 7, 8, 9, 10)), 'day'), true, 'day match'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 7, 8, 9, 10)), 'days'), true, 'plural should work'); + assert.equal(m.isSame(moment(new Date(2012, 1, 2, 7, 8, 9, 10)), 'day'), false, 'year mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 2, 2, 7, 8, 9, 10)), 'day'), false, 'month mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 3, 7, 8, 9, 10)), 'day'), false, 'day mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 0, 0, 0, 0)), 'day'), true, 'exact start of day'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 23, 59, 59, 999)), 'day'), true, 'exact end of day'); + assert.equal(m.isSame(moment(new Date(2011, 1, 3, 0, 0, 0, 0)), 'day'), false, 'start of next day'); + assert.equal(m.isSame(moment(new Date(2011, 1, 1, 23, 59, 59, 999)), 'day'), false, 'end of previous day'); + assert.equal(m.isSame(m, 'day'), true, 'same moments are in the same day'); + assert.equal(+m, +mCopy, 'isSame day should not change moment'); + }); + + test('is same hour', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 8, 9, 10)), 'hour'), true, 'hour match'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 8, 9, 10)), 'hours'), true, 'plural should work'); + assert.equal(m.isSame(moment(new Date(2012, 1, 2, 3, 8, 9, 10)), 'hour'), false, 'year mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 2, 2, 3, 8, 9, 10)), 'hour'), false, 'month mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 3, 3, 8, 9, 10)), 'hour'), false, 'day mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 4, 8, 9, 10)), 'hour'), false, 'hour mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 0, 0, 0)), 'hour'), true, 'exact start of hour'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 59, 59, 999)), 'hour'), true, 'exact end of hour'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 4, 0, 0, 0)), 'hour'), false, 'start of next hour'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 2, 59, 59, 999)), 'hour'), false, 'end of previous hour'); + assert.equal(m.isSame(m, 'hour'), true, 'same moments are in the same hour'); + assert.equal(+m, +mCopy, 'isSame hour should not change moment'); + }); + + test('is same minute', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 9, 10)), 'minute'), true, 'minute match'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 9, 10)), 'minutes'), true, 'plural should work'); + assert.equal(m.isSame(moment(new Date(2012, 1, 2, 3, 4, 9, 10)), 'minute'), false, 'year mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 2, 2, 3, 4, 9, 10)), 'minute'), false, 'month mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 3, 3, 4, 9, 10)), 'minute'), false, 'day mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 4, 4, 9, 10)), 'minute'), false, 'hour mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 5, 9, 10)), 'minute'), false, 'minute mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 0, 0)), 'minute'), true, 'exact start of minute'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 59, 999)), 'minute'), true, 'exact end of minute'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 5, 0, 0)), 'minute'), false, 'start of next minute'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 3, 59, 999)), 'minute'), false, 'end of previous minute'); + assert.equal(m.isSame(m, 'minute'), true, 'same moments are in the same minute'); + assert.equal(+m, +mCopy, 'isSame minute should not change moment'); + }); + + test('is same second', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)), mCopy = moment(m); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 5, 10)), 'second'), true, 'second match'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 5, 10)), 'seconds'), true, 'plural should work'); + assert.equal(m.isSame(moment(new Date(2012, 1, 2, 3, 4, 5, 10)), 'second'), false, 'year mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 2, 2, 3, 4, 5, 10)), 'second'), false, 'month mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 3, 3, 4, 5, 10)), 'second'), false, 'day mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 4, 4, 5, 10)), 'second'), false, 'hour mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 5, 5, 10)), 'second'), false, 'minute mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 6, 10)), 'second'), false, 'second mismatch'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 5, 0)), 'second'), true, 'exact start of second'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 5, 999)), 'second'), true, 'exact end of second'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 6, 0)), 'second'), false, 'start of next second'); + assert.equal(m.isSame(moment(new Date(2011, 1, 2, 3, 4, 4, 999)), 'second'), false, 'end of previous second'); + assert.equal(m.isSame(m, 'second'), true, 'same moments are in the same second'); + assert.equal(+m, +mCopy, 'isSame second should not change moment'); + }); + + test('is same millisecond', function (assert) { + var m = moment(new Date(2011, 3, 2, 3, 4, 5, 10)), mCopy = moment(m); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 5, 10)), 'millisecond'), true, 'millisecond match'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 5, 10)), 'milliseconds'), true, 'plural should work'); + assert.equal(m.isSame(moment(new Date(2012, 3, 2, 3, 4, 5, 10)), 'millisecond'), false, 'year is later'); + assert.equal(m.isSame(moment(new Date(2010, 3, 2, 3, 4, 5, 10)), 'millisecond'), false, 'year is earlier'); + assert.equal(m.isSame(moment(new Date(2011, 4, 2, 3, 4, 5, 10)), 'millisecond'), false, 'month is later'); + assert.equal(m.isSame(moment(new Date(2011, 2, 2, 3, 4, 5, 10)), 'millisecond'), false, 'month is earlier'); + assert.equal(m.isSame(moment(new Date(2011, 3, 3, 3, 4, 5, 10)), 'millisecond'), false, 'day is later'); + assert.equal(m.isSame(moment(new Date(2011, 3, 1, 1, 4, 5, 10)), 'millisecond'), false, 'day is earlier'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 4, 4, 5, 10)), 'millisecond'), false, 'hour is later'); + assert.equal(m.isSame(moment(new Date(2011, 3, 1, 4, 1, 5, 10)), 'millisecond'), false, 'hour is earlier'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 5, 5, 10)), 'millisecond'), false, 'minute is later'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 3, 5, 10)), 'millisecond'), false, 'minute is earlier'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 6, 10)), 'millisecond'), false, 'second is later'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 4, 5)), 'millisecond'), false, 'second is earlier'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 6, 11)), 'millisecond'), false, 'millisecond is later'); + assert.equal(m.isSame(moment(new Date(2011, 3, 2, 3, 4, 4, 9)), 'millisecond'), false, 'millisecond is earlier'); + assert.equal(m.isSame(m, 'millisecond'), true, 'same moments are in the same millisecond'); + assert.equal(+m, +mCopy, 'isSame millisecond should not change moment'); + }); + + test('is same with utc offset moments', function (assert) { + assert.ok(moment.parseZone('2013-02-01T-05:00').isSame(moment('2013-02-01'), 'year'), 'zoned vs local moment'); + assert.ok(moment('2013-02-01').isSame(moment('2013-02-01').utcOffset('-05:00'), 'year'), 'local vs zoned moment'); + assert.ok(moment.parseZone('2013-02-01T-05:00').isSame(moment.parseZone('2013-02-01T-06:30'), 'year'), + 'zoned vs (differently) zoned moment'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('is valid'); + + test('array bad month', function (assert) { + assert.equal(moment([2010, -1]).isValid(), false, 'month -1 invalid'); + assert.equal(moment([2100, 12]).isValid(), false, 'month 12 invalid'); + }); + + test('array good month', function (assert) { + for (var i = 0; i < 12; i++) { + assert.equal(moment([2010, i]).isValid(), true, 'month ' + i); + assert.equal(moment.utc([2010, i]).isValid(), true, 'month ' + i); + } + }); + + test('array bad date', function (assert) { + var tests = [ + moment([2010, 0, 0]), + moment([2100, 0, 32]), + moment.utc([2010, 0, 0]), + moment.utc([2100, 0, 32]) + ], + i, m; + + for (i in tests) { + m = tests[i]; + assert.equal(m.isValid(), false); + } + }); + + test('h/hh with hour > 12', function (assert) { + assert.ok(moment('06/20/2014 11:51 PM', 'MM/DD/YYYY hh:mm A', true).isValid(), '11 for hh'); + assert.ok(moment('06/20/2014 11:51 AM', 'MM/DD/YYYY hh:mm A', true).isValid(), '11 for hh'); + assert.ok(moment('06/20/2014 23:51 PM', 'MM/DD/YYYY hh:mm A').isValid(), 'non-strict validity 23 for hh'); + assert.ok(moment('06/20/2014 23:51 PM', 'MM/DD/YYYY hh:mm A').parsingFlags().bigHour, 'non-strict bigHour 23 for hh'); + assert.ok(!moment('06/20/2014 23:51 PM', 'MM/DD/YYYY hh:mm A', true).isValid(), 'validity 23 for hh'); + assert.ok(moment('06/20/2014 23:51 PM', 'MM/DD/YYYY hh:mm A', true).parsingFlags().bigHour, 'bigHour 23 for hh'); + }); + + test('array bad date leap year', function (assert) { + assert.equal(moment([2010, 1, 29]).isValid(), false, '2010 feb 29'); + assert.equal(moment([2100, 1, 29]).isValid(), false, '2100 feb 29'); + assert.equal(moment([2008, 1, 30]).isValid(), false, '2008 feb 30'); + assert.equal(moment([2000, 1, 30]).isValid(), false, '2000 feb 30'); + + assert.equal(moment.utc([2010, 1, 29]).isValid(), false, 'utc 2010 feb 29'); + assert.equal(moment.utc([2100, 1, 29]).isValid(), false, 'utc 2100 feb 29'); + assert.equal(moment.utc([2008, 1, 30]).isValid(), false, 'utc 2008 feb 30'); + assert.equal(moment.utc([2000, 1, 30]).isValid(), false, 'utc 2000 feb 30'); + }); + + test('string + formats bad date', function (assert) { + assert.equal(moment('2020-00-00', []).isValid(), false, 'invalid on empty array'); + assert.equal(moment('2020-00-00', ['YYYY-MM-DD', 'DD-MM-YYYY']).isValid(), false, 'invalid on all in array'); + assert.equal(moment('2020-00-00', ['DD-MM-YYYY', 'YYYY-MM-DD']).isValid(), false, 'invalid on all in array'); + assert.equal(moment('2020-01-01', ['YYYY-MM-DD', 'DD-MM-YYYY']).isValid(), true, 'valid on first'); + assert.equal(moment('2020-01-01', ['DD-MM-YYYY', 'YYYY-MM-DD']).isValid(), true, 'valid on last'); + assert.equal(moment('2020-01-01', ['YYYY-MM-DD', 'YYYY-DD-MM']).isValid(), true, 'valid on both'); + assert.equal(moment('2020-13-01', ['YYYY-MM-DD', 'YYYY-DD-MM']).isValid(), true, 'valid on last'); + + assert.equal(moment('12-13-2012', ['DD-MM-YYYY', 'YYYY-MM-DD']).isValid(), false, 'month rollover'); + assert.equal(moment('12-13-2012', ['DD-MM-YYYY', 'DD-MM-YYYY']).isValid(), false, 'month rollover'); + assert.equal(moment('38-12-2012', ['DD-MM-YYYY']).isValid(), false, 'day rollover'); + }); + + test('string nonsensical with format', function (assert) { + assert.equal(moment('fail', 'MM-DD-YYYY').isValid(), false, 'string \'fail\' with format \'MM-DD-YYYY\''); + assert.equal(moment('xx-xx-2001', 'DD-MM-YYY').isValid(), true, 'string \'xx-xx-2001\' with format \'MM-DD-YYYY\''); + }); + + test('string with bad month name', function (assert) { + assert.equal(moment('01-Nam-2012', 'DD-MMM-YYYY').isValid(), false, '\'Nam\' is an invalid month'); + assert.equal(moment('01-Aug-2012', 'DD-MMM-YYYY').isValid(), true, '\'Aug\' is a valid month'); + }); + + test('string with spaceless format', function (assert) { + assert.equal(moment('10Sep2001', 'DDMMMYYYY').isValid(), true, 'Parsing 10Sep2001 should result in a valid date'); + }); + + test('invalid string iso 8601', function (assert) { + var tests = [ + '2010-00-00', + '2010-01-00', + '2010-01-40', + '2010-01-01T24:01', // 24:00:00 is actually valid + '2010-01-01T23:60', + '2010-01-01T23:59:60' + ], i; + + for (i = 0; i < tests.length; i++) { + assert.equal(moment(tests[i]).isValid(), false, tests[i] + ' should be invalid'); + assert.equal(moment.utc(tests[i]).isValid(), false, tests[i] + ' should be invalid'); + } + }); + + test('invalid string iso 8601 + timezone', function (assert) { + var tests = [ + '2010-00-00T+00:00', + '2010-01-00T+00:00', + '2010-01-40T+00:00', + '2010-01-40T24:01+00:00', + '2010-01-40T23:60+00:00', + '2010-01-40T23:59:60+00:00', + '2010-01-40T23:59:59.9999+00:00' + ], i; + + for (i = 0; i < tests.length; i++) { + assert.equal(moment(tests[i]).isValid(), false, tests[i] + ' should be invalid'); + assert.equal(moment.utc(tests[i]).isValid(), false, tests[i] + ' should be invalid'); + } + }); + + test('valid string iso 8601 + timezone', function (assert) { + 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', + '2010-01-30T00:00:00.000+07' + ], i; + + for (i = 0; i < tests.length; i++) { + assert.equal(moment(tests[i]).isValid(), true, tests[i] + ' should be valid'); + assert.equal(moment.utc(tests[i]).isValid(), true, tests[i] + ' should be valid'); + } + }); + + test('invalidAt', function (assert) { + assert.equal(moment([2000, 12]).invalidAt(), 1, 'month 12 is invalid: 0-11'); + assert.equal(moment([2000, 1, 30]).invalidAt(), 2, '30 is not a valid february day'); + assert.equal(moment([2000, 1, 29, 25]).invalidAt(), 3, '25 is invalid hour'); + assert.equal(moment([2000, 1, 29, 24, 1]).invalidAt(), 3, '24:01 is invalid hour'); + assert.equal(moment([2000, 1, 29, 23, 60]).invalidAt(), 4, '60 is invalid minute'); + assert.equal(moment([2000, 1, 29, 23, 59, 60]).invalidAt(), 5, '60 is invalid second'); + assert.equal(moment([2000, 1, 29, 23, 59, 59, 1000]).invalidAt(), 6, '1000 is invalid millisecond'); + assert.equal(moment([2000, 1, 29, 23, 59, 59, 999]).invalidAt(), -1, '-1 if everything is fine'); + }); + + test('valid Unix timestamp', function (assert) { + assert.equal(moment(1371065286, 'X').isValid(), true, 'number integer'); + assert.equal(moment(1379066897.0, 'X').isValid(), true, 'number whole 1dp'); + assert.equal(moment(1379066897.7, 'X').isValid(), true, 'number 1dp'); + assert.equal(moment(1379066897.00, 'X').isValid(), true, 'number whole 2dp'); + assert.equal(moment(1379066897.07, 'X').isValid(), true, 'number 2dp'); + assert.equal(moment(1379066897.17, 'X').isValid(), true, 'number 2dp'); + assert.equal(moment(1379066897.000, 'X').isValid(), true, 'number whole 3dp'); + assert.equal(moment(1379066897.007, 'X').isValid(), true, 'number 3dp'); + assert.equal(moment(1379066897.017, 'X').isValid(), true, 'number 3dp'); + assert.equal(moment(1379066897.157, 'X').isValid(), true, 'number 3dp'); + assert.equal(moment('1371065286', 'X').isValid(), true, 'string integer'); + assert.equal(moment('1379066897.', 'X').isValid(), true, 'string trailing .'); + assert.equal(moment('1379066897.0', 'X').isValid(), true, 'string whole 1dp'); + assert.equal(moment('1379066897.7', 'X').isValid(), true, 'string 1dp'); + assert.equal(moment('1379066897.00', 'X').isValid(), true, 'string whole 2dp'); + assert.equal(moment('1379066897.07', 'X').isValid(), true, 'string 2dp'); + assert.equal(moment('1379066897.17', 'X').isValid(), true, 'string 2dp'); + assert.equal(moment('1379066897.000', 'X').isValid(), true, 'string whole 3dp'); + assert.equal(moment('1379066897.007', 'X').isValid(), true, 'string 3dp'); + assert.equal(moment('1379066897.017', 'X').isValid(), true, 'string 3dp'); + assert.equal(moment('1379066897.157', 'X').isValid(), true, 'string 3dp'); + }); + + test('invalid Unix timestamp', function (assert) { + assert.equal(moment(undefined, 'X').isValid(), false, 'undefined'); + assert.equal(moment('undefined', 'X').isValid(), false, 'string undefined'); + try { + assert.equal(moment(null, 'X').isValid(), false, 'null'); + } catch (e) { + assert.ok(true, 'null'); + } + + assert.equal(moment('null', 'X').isValid(), false, 'string null'); + assert.equal(moment([], 'X').isValid(), false, 'array'); + assert.equal(moment('{}', 'X').isValid(), false, 'object'); + try { + assert.equal(moment('', 'X').isValid(), false, 'string empty'); + } catch (e) { + assert.ok(true, 'string empty'); + } + + assert.equal(moment(' ', 'X').isValid(), false, 'string space'); + }); + + test('valid Unix offset milliseconds', function (assert) { + assert.equal(moment(1234567890123, 'x').isValid(), true, 'number integer'); + assert.equal(moment('1234567890123', 'x').isValid(), true, 'string integer'); + }); + + test('invalid Unix offset milliseconds', function (assert) { + assert.equal(moment(undefined, 'x').isValid(), false, 'undefined'); + assert.equal(moment('undefined', 'x').isValid(), false, 'string undefined'); + try { + assert.equal(moment(null, 'x').isValid(), false, 'null'); + } catch (e) { + assert.ok(true, 'null'); + } + + assert.equal(moment('null', 'x').isValid(), false, 'string null'); + assert.equal(moment([], 'x').isValid(), false, 'array'); + assert.equal(moment('{}', 'x').isValid(), false, 'object'); + try { + assert.equal(moment('', 'x').isValid(), false, 'string empty'); + } catch (e) { + assert.ok(true, 'string empty'); + } + + assert.equal(moment(' ', 'x').isValid(), false, 'string space'); + }); + + test('empty', function (assert) { + assert.equal(moment(null).isValid(), false, 'null'); + assert.equal(moment('').isValid(), false, 'empty string'); + assert.equal(moment(null, 'YYYY').isValid(), false, 'format + null'); + assert.equal(moment('', 'YYYY').isValid(), false, 'format + empty string'); + assert.equal(moment(' ', 'YYYY').isValid(), false, 'format + empty when trimmed'); + }); + + test('days of the year', function (assert) { + assert.equal(moment('2010 300', 'YYYY DDDD').isValid(), true, 'day 300 of year valid'); + assert.equal(moment('2010 365', 'YYYY DDDD').isValid(), true, 'day 365 of year valid'); + assert.equal(moment('2010 366', 'YYYY DDDD').isValid(), false, 'day 366 of year invalid'); + assert.equal(moment('2012 365', 'YYYY DDDD').isValid(), true, 'day 365 of leap year valid'); + assert.equal(moment('2012 366', 'YYYY DDDD').isValid(), true, 'day 366 of leap year valid'); + assert.equal(moment('2012 367', 'YYYY DDDD').isValid(), false, 'day 367 of leap year invalid'); + }); + + test('24:00:00.000 is valid', function (assert) { + assert.equal(moment('2014-01-01 24', 'YYYY-MM-DD HH').isValid(), true, '24 is valid'); + assert.equal(moment('2014-01-01 24:00', 'YYYY-MM-DD HH:mm').isValid(), true, '24:00 is valid'); + assert.equal(moment('2014-01-01 24:01', 'YYYY-MM-DD HH:mm').isValid(), false, '24:01 is not valid'); + }); + + test('oddball permissiveness', function (assert) { + //https://github.com/moment/moment/issues/1128 + assert.ok(moment('2010-10-3199', ['MM/DD/YYYY', 'MM-DD-YYYY', 'YYYY-MM-DD']).isValid()); + + //https://github.com/moment/moment/issues/1122 + assert.ok(moment('3:25', ['h:mma', 'hh:mma', 'H:mm', 'HH:mm']).isValid()); + }); + + test('0 hour is invalid in strict', function (assert) { + assert.equal(moment('00:01', 'hh:mm', true).isValid(), false, '00 hour is invalid in strict'); + assert.equal(moment('00:01', 'hh:mm').isValid(), true, '00 hour is valid in normal'); + assert.equal(moment('0:01', 'h:mm', true).isValid(), false, '0 hour is invalid in strict'); + assert.equal(moment('0:01', 'h:mm').isValid(), true, '0 hour is valid in normal'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('leap year'); + + test('leap year', function (assert) { + assert.equal(moment([2010, 0, 1]).isLeapYear(), false, '2010'); + assert.equal(moment([2100, 0, 1]).isLeapYear(), false, '2100'); + assert.equal(moment([2008, 0, 1]).isLeapYear(), true, '2008'); + assert.equal(moment([2000, 0, 1]).isLeapYear(), true, '2000'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('listers'); + + test('default', function (assert) { + assert.deepEqual(moment.months(), ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']); + assert.deepEqual(moment.monthsShort(), ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']); + assert.deepEqual(moment.weekdays(), ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']); + assert.deepEqual(moment.weekdaysShort(), ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']); + assert.deepEqual(moment.weekdaysMin(), ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']); + }); + + test('index', function (assert) { + assert.equal(moment.months(0), 'January'); + assert.equal(moment.months(2), 'March'); + assert.equal(moment.monthsShort(0), 'Jan'); + assert.equal(moment.monthsShort(2), 'Mar'); + assert.equal(moment.weekdays(0), 'Sunday'); + assert.equal(moment.weekdays(2), 'Tuesday'); + assert.equal(moment.weekdaysShort(0), 'Sun'); + assert.equal(moment.weekdaysShort(2), 'Tue'); + assert.equal(moment.weekdaysMin(0), 'Su'); + assert.equal(moment.weekdaysMin(2), 'Tu'); + }); + + test('localized', function (assert) { + var months = 'one_two_three_four_five_six_seven_eight_nine_ten_eleven_twelve'.split('_'), + monthsShort = 'on_tw_th_fo_fi_si_se_ei_ni_te_el_tw'.split('_'), + weekdays = 'one_two_three_four_five_six_seven'.split('_'), + weekdaysShort = 'on_tw_th_fo_fi_si_se'.split('_'), + weekdaysMin = '1_2_3_4_5_6_7'.split('_'); + + moment.locale('numerologists', { + months : months, + monthsShort : monthsShort, + weekdays : weekdays, + weekdaysShort: weekdaysShort, + weekdaysMin: weekdaysMin + }); + + assert.deepEqual(moment.months(), months); + assert.deepEqual(moment.monthsShort(), monthsShort); + assert.deepEqual(moment.weekdays(), weekdays); + assert.deepEqual(moment.weekdaysShort(), weekdaysShort); + assert.deepEqual(moment.weekdaysMin(), weekdaysMin); + + assert.equal(moment.months(0), 'one'); + assert.equal(moment.monthsShort(0), 'on'); + assert.equal(moment.weekdays(0), 'one'); + assert.equal(moment.weekdaysShort(0), 'on'); + assert.equal(moment.weekdaysMin(0), '1'); + + assert.equal(moment.months(2), 'three'); + assert.equal(moment.monthsShort(2), 'th'); + assert.equal(moment.weekdays(2), 'three'); + assert.equal(moment.weekdaysShort(2), 'th'); + assert.equal(moment.weekdaysMin(2), '3'); + }); + + test('with functions', function (assert) { + var monthsShort = 'one_two_three_four_five_six_seven_eight_nine_ten_eleven_twelve'.split('_'), + monthsShortWeird = 'onesy_twosy_threesy_foursy_fivesy_sixsy_sevensy_eightsy_ninesy_tensy_elevensy_twelvesy'.split('_'); + + moment.locale('difficult', { + + monthsShort: function (m, format) { + var arr = format.match(/-MMM-/) ? monthsShortWeird : monthsShort; + return arr[m.month()]; + } + }); + + assert.deepEqual(moment.monthsShort(), monthsShort); + assert.deepEqual(moment.monthsShort('MMM'), monthsShort); + assert.deepEqual(moment.monthsShort('-MMM-'), monthsShortWeird); + + assert.deepEqual(moment.monthsShort('MMM', 2), 'three'); + assert.deepEqual(moment.monthsShort('-MMM-', 2), 'threesy'); + assert.deepEqual(moment.monthsShort(2), 'three'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function each(array, callback) { + var i; + for (i = 0; i < array.length; i++) { + callback(array[i], i, array); + } + } + + var helpers_each = each; + + module('locale', { + setup : function () { + // TODO: Remove once locales are switched to ES6 + helpers_each([{ + name: 'en-gb', + data: {} + }, { + name: 'en-ca', + data: {} + }, { + name: 'es', + data: { + relativeTime: {past: 'hace %s', s: 'unos segundos', d: 'un día'}, + months: 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_') + } + }, { + name: 'fr', + data: {} + }, { + name: 'fr-ca', + data: {} + }, { + name: 'it', + data: {} + }, { + name: 'zh-cn', + data: { + months: '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_') + } + }], function (locale) { + if (moment.locale(locale.name) !== locale.name) { + moment.defineLocale(locale.name, locale.data); + } + }); + moment.locale('en'); + } + }); + + test('library getters and setters', function (assert) { + var r = moment.locale('en'); + + assert.equal(r, 'en', 'locale should return en by default'); + assert.equal(moment.locale(), 'en', 'locale should return en by default'); + + moment.locale('fr'); + assert.equal(moment.locale(), 'fr', 'locale should return the changed locale'); + + moment.locale('en-gb'); + assert.equal(moment.locale(), 'en-gb', 'locale should return the changed locale'); + + moment.locale('en'); + assert.equal(moment.locale(), 'en', 'locale should reset'); + + moment.locale('does-not-exist'); + assert.equal(moment.locale(), 'en', 'locale should reset'); + + moment.locale('EN'); + assert.equal(moment.locale(), 'en', 'Normalize locale key case'); + + moment.locale('EN_gb'); + assert.equal(moment.locale(), 'en-gb', 'Normalize locale key underscore'); + }); + + test('library setter array of locales', function (assert) { + assert.equal(moment.locale(['non-existent', 'fr', 'also-non-existent']), 'fr', 'passing an array uses the first valid locale'); + assert.equal(moment.locale(['es', 'fr', 'also-non-existent']), 'es', 'passing an array uses the first valid locale'); + }); + + test('library setter locale substrings', function (assert) { + assert.equal(moment.locale('fr-crap'), 'fr', 'use substrings'); + assert.equal(moment.locale('fr-does-not-exist'), 'fr', 'uses deep substrings'); + assert.equal(moment.locale('fr-CA-does-not-exist'), 'fr-ca', 'uses deepest substring'); + }); + + test('library getter locale array and substrings', function (assert) { + assert.equal(moment.locale(['en-CH', 'fr']), 'en', 'prefer root locale to shallower ones'); + assert.equal(moment.locale(['en-gb-leeds', 'en-CA']), 'en-gb', 'prefer root locale to shallower ones'); + assert.equal(moment.locale(['en-fake', 'en-CA']), 'en-ca', 'prefer alternatives with shared roots'); + assert.equal(moment.locale(['en-fake', 'en-fake2', 'en-ca']), 'en-ca', 'prefer alternatives with shared roots'); + assert.equal(moment.locale(['fake-CA', 'fake-MX', 'fr']), 'fr', 'always find something if possible'); + assert.equal(moment.locale(['fake-CA', 'fake-MX', 'fr']), 'fr', 'always find something if possible'); + assert.equal(moment.locale(['fake-CA', 'fake-MX', 'fr-fake-fake-fake']), 'fr', 'always find something if possible'); + assert.equal(moment.locale(['en', 'en-CA']), 'en', 'prefer earlier if it works'); + }); + + test('library ensure inheritance', function (assert) { + moment.locale('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. + }); + + assert.equal(moment([2012, 5, 6]).format('MMMM'), 'July', 'Override some of the configs'); + assert.equal(moment([2012, 5, 6]).format('MMM'), 'Jun', 'But not all of them'); + }); + + test('library ensure inheritance LT L LL LLL LLLL', function (assert) { + var locale = 'test-inherit-lt'; + + moment.defineLocale(locale, { + 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.locale('es'); + + assert.equal(moment().locale(locale).calendar(), 'sameDay -LT-', 'Should use instance locale in LT formatting'); + assert.equal(moment().add(1, 'days').locale(locale).calendar(), 'nextDay -L-', 'Should use instance locale in L formatting'); + assert.equal(moment().add(-1, 'days').locale(locale).calendar(), 'lastDay -LLL-', 'Should use instance locale in LL formatting'); + assert.equal(moment().add(4, 'days').locale(locale).calendar(), 'nextWeek -LL-', 'Should use instance locale in LLL formatting'); + assert.equal(moment().add(-4, 'days').locale(locale).calendar(), 'lastWeek -LLLL-', 'Should use instance locale in LLLL formatting'); + }); + + test('library localeData', function (assert) { + moment.locale('en'); + + var jan = moment([2000, 0]); + + assert.equal(moment.localeData().months(jan), 'January', 'no arguments returns global'); + assert.equal(moment.localeData('zh-cn').months(jan), '一月', 'a string returns the locale based on key'); + assert.equal(moment.localeData(moment().locale('es')).months(jan), 'Enero', 'if you pass in a moment it uses the moment\'s locale'); + }); + + test('library deprecations', function (assert) { + moment.lang('dude', {months: ['Movember']}); + assert.equal(moment.locale(), 'dude', 'setting the lang sets the locale'); + assert.equal(moment.lang(), moment.locale()); + assert.equal(moment.langData(), moment.localeData(), 'langData is localeData'); + }); + + test('defineLocale', function (assert) { + moment.locale('en'); + moment.defineLocale('dude', {months: ['Movember']}); + assert.equal(moment().locale(), 'dude', 'defineLocale also sets it'); + assert.equal(moment().locale('dude').locale(), 'dude', 'defineLocale defines a locale'); + }); + + test('library convenience', function (assert) { + moment.locale('something', {week: {dow: 3}}); + moment.locale('something'); + assert.equal(moment.locale(), 'something', 'locale can be used to create the locale too'); + }); + + test('firstDayOfWeek firstDayOfYear locale getters', function (assert) { + moment.locale('something', {week: {dow: 3, doy: 4}}); + moment.locale('something'); + assert.equal(moment.localeData().firstDayOfWeek(), 3, 'firstDayOfWeek'); + assert.equal(moment.localeData().firstDayOfYear(), 4, 'firstDayOfYear'); + }); + + test('instance locale method', function (assert) { + moment.locale('en'); + + assert.equal(moment([2012, 5, 6]).format('MMMM'), 'June', 'Normally default to global'); + assert.equal(moment([2012, 5, 6]).locale('es').format('MMMM'), 'Junio', 'Use the instance specific locale'); + assert.equal(moment([2012, 5, 6]).format('MMMM'), 'June', 'Using an instance specific locale does not affect other moments'); + }); + + test('instance locale method with array', function (assert) { + var m = moment().locale(['non-existent', 'fr', 'also-non-existent']); + assert.equal(m.locale(), 'fr', 'passing an array uses the first valid locale'); + m = moment().locale(['es', 'fr', 'also-non-existent']); + assert.equal(m.locale(), 'es', 'passing an array uses the first valid locale'); + }); + + test('instance getter locale substrings', function (assert) { + var m = moment(); + + m.locale('fr-crap'); + assert.equal(m.locale(), 'fr', 'use substrings'); + + m.locale('fr-does-not-exist'); + assert.equal(m.locale(), 'fr', 'uses deep substrings'); + }); + + test('instance locale persists with manipulation', function (assert) { + moment.locale('en'); + + assert.equal(moment([2012, 5, 6]).locale('es').add({days: 1}).format('MMMM'), 'Junio', 'With addition'); + assert.equal(moment([2012, 5, 6]).locale('es').day(0).format('MMMM'), 'Junio', 'With day getter'); + assert.equal(moment([2012, 5, 6]).locale('es').endOf('day').format('MMMM'), 'Junio', 'With endOf'); + }); + + test('instance locale persists with cloning', function (assert) { + moment.locale('en'); + + var a = moment([2012, 5, 6]).locale('es'), + b = a.clone(), + c = moment(a); + + assert.equal(b.format('MMMM'), 'Junio', 'using moment.fn.clone()'); + assert.equal(b.format('MMMM'), 'Junio', 'using moment()'); + }); + + test('duration locale method', function (assert) { + moment.locale('en'); + + assert.equal(moment.duration({seconds: 44}).humanize(), 'a few seconds', 'Normally default to global'); + assert.equal(moment.duration({seconds: 44}).locale('es').humanize(), 'unos segundos', 'Use the instance specific locale'); + assert.equal(moment.duration({seconds: 44}).humanize(), 'a few seconds', 'Using an instance specific locale does not affect other durations'); + }); + + test('duration locale persists with cloning', function (assert) { + moment.locale('en'); + + var a = moment.duration({seconds: 44}).locale('es'), + b = moment.duration(a); + + assert.equal(b.humanize(), 'unos segundos', 'using moment.duration()'); + }); + + test('changing the global locale doesn\'t affect existing duration instances', function (assert) { + var mom = moment.duration(); + moment.locale('fr'); + assert.equal('en', mom.locale()); + }); + + test('duration deprecations', function (assert) { + assert.equal(moment.duration().lang(), moment.duration().localeData(), 'duration.lang is the same as duration.localeData'); + }); + + test('from and fromNow with invalid date', function (assert) { + assert.equal(moment(NaN).from(), 'Invalid date', 'moment.from with invalid moment'); + assert.equal(moment(NaN).fromNow(), 'Invalid date', 'moment.fromNow with invalid moment'); + }); + + test('from relative time future', function (assert) { + var start = moment([2007, 1, 28]); + + assert.equal(start.from(moment([2007, 1, 28]).subtract({s: 44})), 'in a few seconds', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({s: 45})), 'in a minute', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({s: 89})), 'in a minute', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({s: 90})), 'in 2 minutes', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({m: 44})), 'in 44 minutes', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({m: 45})), 'in an hour', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({m: 89})), 'in an hour', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({m: 90})), 'in 2 hours', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({h: 5})), 'in 5 hours', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({h: 21})), 'in 21 hours', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({h: 22})), 'in a day', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({h: 35})), 'in a day', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({h: 36})), 'in 2 days', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 1})), 'in a day', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 5})), 'in 5 days', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 25})), 'in 25 days', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 26})), 'in a month', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 30})), 'in a month', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 45})), 'in a month', '45 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 47})), 'in 2 months', '47 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 74})), 'in 2 months', '74 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 78})), 'in 3 months', '78 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({M: 1})), 'in a month', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({M: 5})), 'in 5 months', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 315})), 'in 10 months', '315 days = 10 months'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 344})), 'in a year', '344 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 345})), 'in a year', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({d: 548})), 'in 2 years', '548 days = in 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({y: 1})), 'in a year', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).subtract({y: 5})), 'in 5 years', '5 years = 5 years'); + }); + + test('from relative time past', function (assert) { + var start = moment([2007, 1, 28]); + + assert.equal(start.from(moment([2007, 1, 28]).add({s: 44})), 'a few seconds ago', '44 seconds = a few seconds'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 45})), 'a minute ago', '45 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 89})), 'a minute ago', '89 seconds = a minute'); + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90})), '2 minutes ago', '90 seconds = 2 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 44})), '44 minutes ago', '44 minutes = 44 minutes'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 45})), 'an hour ago', '45 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 89})), 'an hour ago', '89 minutes = an hour'); + assert.equal(start.from(moment([2007, 1, 28]).add({m: 90})), '2 hours ago', '90 minutes = 2 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 5})), '5 hours ago', '5 hours = 5 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 21})), '21 hours ago', '21 hours = 21 hours'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 22})), 'a day ago', '22 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 35})), 'a day ago', '35 hours = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({h: 36})), '2 days ago', '36 hours = 2 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 1})), 'a day ago', '1 day = a day'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 5})), '5 days ago', '5 days = 5 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 25})), '25 days ago', '25 days = 25 days'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 26})), 'a month ago', '26 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 30})), 'a month ago', '30 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 43})), 'a month ago', '43 days = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 46})), '2 months ago', '46 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 74})), '2 months ago', '75 days = 2 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 76})), '3 months ago', '76 days = 3 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 1})), 'a month ago', '1 month = a month'); + assert.equal(start.from(moment([2007, 1, 28]).add({M: 5})), '5 months ago', '5 months = 5 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 315})), '10 months ago', '315 days = 10 months'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 344})), 'a year ago', '344 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 345})), 'a year ago', '345 days = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({d: 548})), '2 years ago', '548 days = 2 years'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 1})), 'a year ago', '1 year = a year'); + assert.equal(start.from(moment([2007, 1, 28]).add({y: 5})), '5 years ago', '5 years = 5 years'); + }); + + test('instance locale used with from', function (assert) { + moment.locale('en'); + + var a = moment([2012, 5, 6]).locale('es'), + b = moment([2012, 5, 7]); + + assert.equal(a.from(b), 'hace un día', 'preserve locale of first moment'); + assert.equal(b.from(a), 'in a day', 'do not preserve locale of second moment'); + }); + + test('instance localeData', function (assert) { + moment.defineLocale('dude', {week: {dow: 3}}); + assert.equal(moment().locale('dude').localeData()._week.dow, 3); + }); + + test('month name callback function', function (assert) { + function fakeReplace(m, format) { + if (/test/.test(format)) { + return 'test'; + } + if (m.date() === 1) { + return 'date'; + } + return 'default'; + } + + moment.locale('made-up-2', { + months : fakeReplace, + monthsShort : fakeReplace, + weekdays : fakeReplace, + weekdaysShort : fakeReplace, + weekdaysMin : fakeReplace + }); + + assert.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'); + assert.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'); + assert.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('changing parts of a locale config', function (assert) { + moment.locale('partial-lang', { + months : 'a b c d e f g h i j k l'.split(' ') + }); + + assert.equal(moment([2011, 0, 1]).format('MMMM'), 'a', 'should be able to set locale values when creating the localeuage'); + + moment.locale('partial-lang', { + monthsShort : 'A B C D E F G H I J K L'.split(' ') + }); + + assert.equal(moment([2011, 0, 1]).format('MMMM MMM'), 'a A', 'should be able to set locale values after creating the localeuage'); + }); + + test('start/endOf week feature for first-day-is-monday locales', function (assert) { + moment.locale('monday-lang', { + week : { + dow : 1 // Monday is the first day of the week + } + }); + + moment.locale('monday-lang'); + assert.equal(moment([2013, 0, 1]).startOf('week').day(), 1, 'for locale monday-lang first day of the week should be monday'); + assert.equal(moment([2013, 0, 1]).endOf('week').day(), 0, 'for locale monday-lang last day of the week should be sunday'); + }); + + test('meridiem parsing', function (assert) { + moment.locale('meridiem-parsing', { + meridiemParse : /[bd]/i, + isPM : function (input) { + return input === 'b'; + } + }); + + moment.locale('meridiem-parsing'); + assert.equal(moment('2012-01-01 3b', 'YYYY-MM-DD ha').hour(), 15, 'Custom parsing of meridiem should work'); + assert.equal(moment('2012-01-01 3d', 'YYYY-MM-DD ha').hour(), 3, 'Custom parsing of meridiem should work'); + }); + + test('invalid date formatting', function (assert) { + moment.locale('has-invalid', { + invalidDate: 'KHAAAAAAAAAAAN!' + }); + + assert.equal(moment.invalid().format(), 'KHAAAAAAAAAAAN!'); + assert.equal(moment.invalid().format('YYYY-MM-DD'), 'KHAAAAAAAAAAAN!'); + }); + + test('return locale name', function (assert) { + var registered = moment.locale('return-this', {}); + + assert.equal(registered, 'return-this', 'returns the locale configured'); + }); + + test('changing the global locale doesn\'t affect existing instances', function (assert) { + var mom = moment(); + moment.locale('fr'); + assert.equal('en', mom.locale()); + }); + + test('setting a language on instance returns the original moment for chaining', function (assert) { + var mom = moment(); + + assert.equal(mom.lang('fr'), mom, 'setting the language (lang) returns the original moment for chaining'); + assert.equal(mom.locale('it'), mom, 'setting the language (locale) returns the original moment for chaining'); + }); + + test('lang(key) changes the language of the instance', function (assert) { + var m = moment().month(0); + m.lang('fr'); + assert.equal(m.locale(), 'fr', 'm.lang(key) changes instance locale'); + }); + + test('moment#locale(false) resets to global locale', function (assert) { + var m = moment(); + + moment.locale('fr'); + m.locale('it'); + + assert.equal(moment.locale(), 'fr', 'global locale is it'); + assert.equal(m.locale(), 'it', 'instance locale is it'); + m.locale(false); + assert.equal(m.locale(), 'fr', 'instance locale reset to global locale'); + }); + + test('moment().locale with missing key doesn\'t change locale', function (assert) { + assert.equal(moment().locale('boo').localeData(), moment.localeData(), + 'preserve global locale in case of bad locale id'); + }); + + test('moment().lang with missing key doesn\'t change locale', function (assert) { + assert.equal(moment().lang('boo').localeData(), moment.localeData(), + 'preserve global locale in case of bad locale id'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('min max'); + + test('min', function (assert) { + var now = moment(), + future = now.clone().add(1, 'month'), + past = now.clone().subtract(1, 'month'); + + assert.equal(moment.min(now, future, past), past, 'min(now, future, past)'); + assert.equal(moment.min(future, now, past), past, 'min(future, now, past)'); + assert.equal(moment.min(future, past, now), past, 'min(future, past, now)'); + assert.equal(moment.min(past, future, now), past, 'min(past, future, now)'); + assert.equal(moment.min(now, past), past, 'min(now, past)'); + assert.equal(moment.min(past, now), past, 'min(past, now)'); + assert.equal(moment.min(now), now, 'min(now, past)'); + + assert.equal(moment.min([now, future, past]), past, 'min([now, future, past])'); + assert.equal(moment.min([now, past]), past, 'min(now, past)'); + assert.equal(moment.min([now]), now, 'min(now)'); + }); + + test('max', function (assert) { + var now = moment(), + future = now.clone().add(1, 'month'), + past = now.clone().subtract(1, 'month'); + + assert.equal(moment.max(now, future, past), future, 'max(now, future, past)'); + assert.equal(moment.max(future, now, past), future, 'max(future, now, past)'); + assert.equal(moment.max(future, past, now), future, 'max(future, past, now)'); + assert.equal(moment.max(past, future, now), future, 'max(past, future, now)'); + assert.equal(moment.max(now, past), now, 'max(now, past)'); + assert.equal(moment.max(past, now), now, 'max(past, now)'); + assert.equal(moment.max(now), now, 'max(now, past)'); + + assert.equal(moment.max([now, future, past]), future, 'max([now, future, past])'); + assert.equal(moment.max([now, past]), now, 'max(now, past)'); + assert.equal(moment.max([now]), now, 'max(now)'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('mutable'); + + test('manipulation methods', function (assert) { + var m = moment(); + + assert.equal(m, m.year(2011), 'year() should be mutable'); + assert.equal(m, m.month(1), 'month() should be mutable'); + assert.equal(m, m.hours(7), 'hours() should be mutable'); + assert.equal(m, m.minutes(33), 'minutes() should be mutable'); + assert.equal(m, m.seconds(44), 'seconds() should be mutable'); + assert.equal(m, m.milliseconds(55), 'milliseconds() should be mutable'); + assert.equal(m, m.day(2), 'day() should be mutable'); + assert.equal(m, m.startOf('week'), 'startOf() should be mutable'); + assert.equal(m, m.add(1, 'days'), 'add() should be mutable'); + assert.equal(m, m.subtract(2, 'years'), 'subtract() should be mutable'); + assert.equal(m, m.local(), 'local() should be mutable'); + assert.equal(m, m.utc(), 'utc() should be mutable'); + }); + + test('non mutable methods', function (assert) { + var m = moment(); + assert.notEqual(m, m.clone(), 'clone() should not be mutable'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('normalize units'); + + test('normalize units', function (assert) { + var fullKeys = ['year', 'quarter', 'month', 'isoWeek', 'week', 'day', 'hour', 'minute', 'second', 'millisecond', 'date', 'dayOfYear', 'weekday', 'isoWeekday', 'weekYear', 'isoWeekYear'], + aliases = ['y', 'Q', 'M', 'W', 'w', 'd', 'h', 'm', 's', 'ms', 'D', 'DDD', 'e', 'E', 'gg', 'GG'], + length = fullKeys.length, + fullKey, + fullKeyCaps, + fullKeyPlural, + fullKeyCapsPlural, + fullKeyLower, + alias, + index; + + for (index = 0; index < length; index += 1) { + fullKey = fullKeys[index]; + fullKeyCaps = fullKey.toUpperCase(); + fullKeyLower = fullKey.toLowerCase(); + fullKeyPlural = fullKey + 's'; + fullKeyCapsPlural = fullKeyCaps + 's'; + alias = aliases[index]; + assert.equal(moment.normalizeUnits(fullKey), fullKey, 'Testing full key ' + fullKey); + assert.equal(moment.normalizeUnits(fullKeyCaps), fullKey, 'Testing full key capitalised ' + fullKey); + assert.equal(moment.normalizeUnits(fullKeyPlural), fullKey, 'Testing full key plural ' + fullKey); + assert.equal(moment.normalizeUnits(fullKeyCapsPlural), fullKey, 'Testing full key capitalised and plural ' + fullKey); + assert.equal(moment.normalizeUnits(alias), fullKey, 'Testing alias ' + fullKey); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('parsing flags'); + + function flags () { + return moment.apply(null, arguments).parsingFlags(); + } + + test('overflow with array', function (assert) { + //months + assert.equal(flags([2010, 0]).overflow, -1, 'month 0 valid'); + assert.equal(flags([2010, 1]).overflow, -1, 'month 1 valid'); + assert.equal(flags([2010, -1]).overflow, 1, 'month -1 invalid'); + assert.equal(flags([2100, 12]).overflow, 1, 'month 12 invalid'); + + //days + assert.equal(flags([2010, 1, 16]).overflow, -1, 'date valid'); + assert.equal(flags([2010, 1, -1]).overflow, 2, 'date -1 invalid'); + assert.equal(flags([2010, 1, 0]).overflow, 2, 'date 0 invalid'); + assert.equal(flags([2010, 1, 32]).overflow, 2, 'date 32 invalid'); + assert.equal(flags([2012, 1, 29]).overflow, -1, 'date leap year valid'); + assert.equal(flags([2010, 1, 29]).overflow, 2, 'date leap year invalid'); + + //hours + assert.equal(flags([2010, 1, 1, 8]).overflow, -1, 'hour valid'); + assert.equal(flags([2010, 1, 1, 0]).overflow, -1, 'hour 0 valid'); + assert.equal(flags([2010, 1, 1, -1]).overflow, 3, 'hour -1 invalid'); + assert.equal(flags([2010, 1, 1, 25]).overflow, 3, 'hour 25 invalid'); + assert.equal(flags([2010, 1, 1, 24, 1]).overflow, 3, 'hour 24:01 invalid'); + + //minutes + assert.equal(flags([2010, 1, 1, 8, 15]).overflow, -1, 'minute valid'); + assert.equal(flags([2010, 1, 1, 8, 0]).overflow, -1, 'minute 0 valid'); + assert.equal(flags([2010, 1, 1, 8, -1]).overflow, 4, 'minute -1 invalid'); + assert.equal(flags([2010, 1, 1, 8, 60]).overflow, 4, 'minute 60 invalid'); + + //seconds + assert.equal(flags([2010, 1, 1, 8, 15, 12]).overflow, -1, 'second valid'); + assert.equal(flags([2010, 1, 1, 8, 15, 0]).overflow, -1, 'second 0 valid'); + assert.equal(flags([2010, 1, 1, 8, 15, -1]).overflow, 5, 'second -1 invalid'); + assert.equal(flags([2010, 1, 1, 8, 15, 60]).overflow, 5, 'second 60 invalid'); + + //milliseconds + assert.equal(flags([2010, 1, 1, 8, 15, 12, 345]).overflow, -1, 'millisecond valid'); + assert.equal(flags([2010, 1, 1, 8, 15, 12, 0]).overflow, -1, 'millisecond 0 valid'); + assert.equal(flags([2010, 1, 1, 8, 15, 12, -1]).overflow, 6, 'millisecond -1 invalid'); + assert.equal(flags([2010, 1, 1, 8, 15, 12, 1000]).overflow, 6, 'millisecond 1000 invalid'); + + // 24 hrs + assert.equal(flags([2010, 1, 1, 24, 0, 0, 0]).overflow, -1, '24:00:00.000 is fine'); + assert.equal(flags([2010, 1, 1, 24, 1, 0, 0]).overflow, 3, '24:01:00.000 is wrong hour'); + assert.equal(flags([2010, 1, 1, 24, 0, 1, 0]).overflow, 3, '24:00:01.000 is wrong hour'); + assert.equal(flags([2010, 1, 1, 24, 0, 0, 1]).overflow, 3, '24:00:00.001 is wrong hour'); + }); + + test('overflow without format', function (assert) { + //months + assert.equal(flags('2001-01', 'YYYY-MM').overflow, -1, 'month 1 valid'); + assert.equal(flags('2001-12', 'YYYY-MM').overflow, -1, 'month 12 valid'); + assert.equal(flags('2001-13', 'YYYY-MM').overflow, 1, 'month 13 invalid'); + + //days + assert.equal(flags('2010-01-16', 'YYYY-MM-DD').overflow, -1, 'date 16 valid'); + assert.equal(flags('2010-01-0', 'YYYY-MM-DD').overflow, 2, 'date 0 invalid'); + assert.equal(flags('2010-01-32', 'YYYY-MM-DD').overflow, 2, 'date 32 invalid'); + assert.equal(flags('2012-02-29', 'YYYY-MM-DD').overflow, -1, 'date leap year valid'); + assert.equal(flags('2010-02-29', 'YYYY-MM-DD').overflow, 2, 'date leap year invalid'); + + //days of the year + assert.equal(flags('2010 300', 'YYYY DDDD').overflow, -1, 'day 300 of year valid'); + assert.equal(flags('2010 365', 'YYYY DDDD').overflow, -1, 'day 365 of year valid'); + assert.equal(flags('2010 366', 'YYYY DDDD').overflow, 2, 'day 366 of year invalid'); + assert.equal(flags('2012 366', 'YYYY DDDD').overflow, -1, 'day 366 of leap year valid'); + assert.equal(flags('2012 367', 'YYYY DDDD').overflow, 2, 'day 367 of leap year invalid'); + + //hours + assert.equal(flags('08', 'HH').overflow, -1, 'hour valid'); + assert.equal(flags('00', 'HH').overflow, -1, 'hour 0 valid'); + assert.equal(flags('25', 'HH').overflow, 3, 'hour 25 invalid'); + assert.equal(flags('24:01', 'HH:mm').overflow, 3, 'hour 24:01 invalid'); + + //minutes + assert.equal(flags('08:15', 'HH:mm').overflow, -1, 'minute valid'); + assert.equal(flags('08:00', 'HH:mm').overflow, -1, 'minute 0 valid'); + assert.equal(flags('08:60', 'HH:mm').overflow, 4, 'minute 60 invalid'); + + //seconds + assert.equal(flags('08:15:12', 'HH:mm:ss').overflow, -1, 'second valid'); + assert.equal(flags('08:15:00', 'HH:mm:ss').overflow, -1, 'second 0 valid'); + assert.equal(flags('08:15:60', 'HH:mm:ss').overflow, 5, 'second 60 invalid'); + + //milliseconds + assert.equal(flags('08:15:12:345', 'HH:mm:ss:SSSS').overflow, -1, 'millisecond valid'); + assert.equal(flags('08:15:12:000', 'HH:mm:ss:SSSS').overflow, -1, 'millisecond 0 valid'); + + //this is OK because we don't match the last digit, so it's 100 ms + assert.equal(flags('08:15:12:1000', 'HH:mm:ss:SSSS').overflow, -1, 'millisecond 1000 actually valid'); + }); + + test('extra tokens', function (assert) { + assert.deepEqual(flags('1982-05-25', 'YYYY-MM-DD').unusedTokens, [], 'nothing extra'); + assert.deepEqual(flags('1982-05', 'YYYY-MM-DD').unusedTokens, ['DD'], 'extra formatting token'); + assert.deepEqual(flags('1982', 'YYYY-MM-DD').unusedTokens, ['MM', 'DD'], 'multiple extra formatting tokens'); + assert.deepEqual(flags('1982-05', 'YYYY-MM-').unusedTokens, [], 'extra non-formatting token'); + assert.deepEqual(flags('1982-05-', 'YYYY-MM-DD').unusedTokens, ['DD'], 'non-extra non-formatting token'); + assert.deepEqual(flags('1982 05 1982', 'YYYY-MM-DD').unusedTokens, [], 'different non-formatting token'); + }); + + test('extra tokens strict', function (assert) { + assert.deepEqual(flags('1982-05-25', 'YYYY-MM-DD', true).unusedTokens, [], 'nothing extra'); + assert.deepEqual(flags('1982-05', 'YYYY-MM-DD', true).unusedTokens, ['-', 'DD'], 'extra formatting token'); + assert.deepEqual(flags('1982', 'YYYY-MM-DD', true).unusedTokens, ['-', 'MM', '-', 'DD'], 'multiple extra formatting tokens'); + assert.deepEqual(flags('1982-05', 'YYYY-MM-', true).unusedTokens, ['-'], 'extra non-formatting token'); + assert.deepEqual(flags('1982-05-', 'YYYY-MM-DD', true).unusedTokens, ['DD'], 'non-extra non-formatting token'); + assert.deepEqual(flags('1982 05 1982', 'YYYY-MM-DD', true).unusedTokens, ['-', '-'], 'different non-formatting token'); + }); + + test('unused input', function (assert) { + assert.deepEqual(flags('1982-05-25', 'YYYY-MM-DD').unusedInput, [], 'normal input'); + assert.deepEqual(flags('1982-05-25 this is more stuff', 'YYYY-MM-DD').unusedInput, [' this is more stuff'], 'trailing nonsense'); + assert.deepEqual(flags('1982-05-25 09:30', 'YYYY-MM-DD').unusedInput, [' 09:30'], ['trailing legit-looking input']); + assert.deepEqual(flags('1982-05-25 some junk', 'YYYY-MM-DD [some junk]').unusedInput, [], 'junk that actually gets matched'); + assert.deepEqual(flags('stuff at beginning 1982-05-25', 'YYYY-MM-DD').unusedInput, ['stuff at beginning '], 'leading junk'); + assert.deepEqual(flags('junk 1982 more junk 05 yet more junk25', 'YYYY-MM-DD').unusedInput, ['junk ', ' more junk ', ' yet more junk'], 'interstitial junk'); + }); + + test('unused input strict', function (assert) { + assert.deepEqual(flags('1982-05-25', 'YYYY-MM-DD', true).unusedInput, [], 'normal input'); + assert.deepEqual(flags('1982-05-25 this is more stuff', 'YYYY-MM-DD', true).unusedInput, [' this is more stuff'], 'trailing nonsense'); + assert.deepEqual(flags('1982-05-25 09:30', 'YYYY-MM-DD', true).unusedInput, [' 09:30'], ['trailing legit-looking input']); + assert.deepEqual(flags('1982-05-25 some junk', 'YYYY-MM-DD [some junk]', true).unusedInput, [], 'junk that actually gets matched'); + assert.deepEqual(flags('stuff at beginning 1982-05-25', 'YYYY-MM-DD', true).unusedInput, ['stuff at beginning '], 'leading junk'); + assert.deepEqual(flags('junk 1982 more junk 05 yet more junk25', 'YYYY-MM-DD', true).unusedInput, ['junk ', ' more junk ', ' yet more junk'], 'interstitial junk'); + }); + + test('chars left over', function (assert) { + assert.equal(flags('1982-05-25', 'YYYY-MM-DD').charsLeftOver, 0, 'normal input'); + assert.equal(flags('1982-05-25 this is more stuff', 'YYYY-MM-DD').charsLeftOver, ' this is more stuff'.length, 'trailing nonsense'); + assert.equal(flags('1982-05-25 09:30', 'YYYY-MM-DD').charsLeftOver, ' 09:30'.length, 'trailing legit-looking input'); + assert.equal(flags('stuff at beginning 1982-05-25', 'YYYY-MM-DD').charsLeftOver, 'stuff at beginning '.length, 'leading junk'); + assert.equal(flags('1982 junk 05 more junk25', 'YYYY-MM-DD').charsLeftOver, [' junk ', ' more junk'].join('').length, 'interstitial junk'); + assert.equal(flags('stuff at beginning 1982 junk 05 more junk25', 'YYYY-MM-DD').charsLeftOver, ['stuff at beginning ', ' junk ', ' more junk'].join('').length, 'leading and interstitial junk'); + }); + + test('empty', function (assert) { + assert.equal(flags('1982-05-25', 'YYYY-MM-DD').empty, false, 'normal input'); + assert.equal(flags('nothing here', 'YYYY-MM-DD').empty, true, 'pure garbage'); + assert.equal(flags('junk but has the number 2000 in it', 'YYYY-MM-DD').empty, false, 'only mostly garbage'); + assert.equal(flags('', 'YYYY-MM-DD').empty, true, 'empty string'); + assert.equal(flags('', 'YYYY-MM-DD').empty, true, 'blank string'); + }); + + test('null', function (assert) { + assert.equal(flags('1982-05-25', 'YYYY-MM-DD').nullInput, false, 'normal input'); + assert.equal(flags(null).nullInput, true, 'just null'); + assert.equal(flags(null, 'YYYY-MM-DD').nullInput, true, 'null with format'); + }); + + test('invalid month', function (assert) { + assert.equal(flags('1982 May', 'YYYY MMMM').invalidMonth, null, 'normal input'); + assert.equal(flags('1982 Laser', 'YYYY MMMM').invalidMonth, 'Laser', 'bad month name'); + }); + + test('empty format array', function (assert) { + assert.equal(flags('1982 May', ['YYYY MMM']).invalidFormat, false, 'empty format array'); + assert.equal(flags('1982 May', []).invalidFormat, true, 'empty format array'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + var symbolMap = { + '1': '!', + '2': '@', + '3': '#', + '4': '$', + '5': '%', + '6': '^', + '7': '&', + '8': '*', + '9': '(', + '0': ')' + }, + numberMap = { + '!': '1', + '@': '2', + '#': '3', + '$': '4', + '%': '5', + '^': '6', + '&': '7', + '*': '8', + '(': '9', + ')': '0' + }; + + module('preparse and postformat', { + setup: function () { + moment.locale('symbol', { + 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]; + }); + } + }); + } + }); + + test('transform', function (assert) { + assert.equal(moment.utc('@)!@-)*-@&', 'YYYY-MM-DD').unix(), 1346025600, 'preparse string + format'); + assert.equal(moment.utc('@)!@-)*-@&').unix(), 1346025600, 'preparse ISO8601 string'); + assert.equal(moment.unix(1346025600).utc().format('YYYY-MM-DD'), '@)!@-)*-@&', 'postformat'); + }); + + test('transform from', function (assert) { + var start = moment([2007, 1, 28]); + + assert.equal(start.from(moment([2007, 1, 28]).add({s: 90}), true), '@ minutes', 'postformat should work on moment.fn.from'); + assert.equal(moment().add(6, 'd').fromNow(true), '^ days', 'postformat should work on moment.fn.fromNow'); + assert.equal(moment.duration(10, 'h').humanize(), '!) hours', 'postformat should work on moment.duration.fn.humanize'); + }); + + test('calendar day', function (assert) { + var a = moment().hours(2).minutes(0).seconds(0); + + assert.equal(moment(a).calendar(), 'Today at @:)) AM', 'today at the same time'); + assert.equal(moment(a).add({m: 25}).calendar(), 'Today at @:@% AM', 'Now plus 25 min'); + assert.equal(moment(a).add({h: 1}).calendar(), 'Today at #:)) AM', 'Now plus 1 hour'); + assert.equal(moment(a).add({d: 1}).calendar(), 'Tomorrow at @:)) AM', 'tomorrow at the same time'); + assert.equal(moment(a).subtract({h: 1}).calendar(), 'Today at !:)) AM', 'Now minus 1 hour'); + assert.equal(moment(a).subtract({d: 1}).calendar(), 'Yesterday at @:)) AM', 'yesterday at the same time'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('quarter'); + + test('library quarter getter', function (assert) { + assert.equal(moment([1985, 1, 4]).quarter(), 1, 'Feb 4 1985 is Q1'); + assert.equal(moment([2029, 8, 18]).quarter(), 3, 'Sep 18 2029 is Q3'); + assert.equal(moment([2013, 3, 24]).quarter(), 2, 'Apr 24 2013 is Q2'); + assert.equal(moment([2015, 2, 5]).quarter(), 1, 'Mar 5 2015 is Q1'); + assert.equal(moment([1970, 0, 2]).quarter(), 1, 'Jan 2 1970 is Q1'); + assert.equal(moment([2001, 11, 12]).quarter(), 4, 'Dec 12 2001 is Q4'); + assert.equal(moment([2000, 0, 2]).quarter(), 1, 'Jan 2 2000 is Q1'); + }); + + test('quarter setter singular', function (assert) { + var m = moment([2014, 4, 11]); + assert.equal(m.quarter(2).month(), 4, 'set same quarter'); + assert.equal(m.quarter(3).month(), 7, 'set 3rd quarter'); + assert.equal(m.quarter(1).month(), 1, 'set 1st quarter'); + assert.equal(m.quarter(4).month(), 10, 'set 4th quarter'); + }); + + test('quarter setter plural', function (assert) { + var m = moment([2014, 4, 11]); + assert.equal(m.quarters(2).month(), 4, 'set same quarter'); + assert.equal(m.quarters(3).month(), 7, 'set 3rd quarter'); + assert.equal(m.quarters(1).month(), 1, 'set 1st quarter'); + assert.equal(m.quarters(4).month(), 10, 'set 4th quarter'); + }); + + test('quarter setter programmatic', function (assert) { + var m = moment([2014, 4, 11]); + assert.equal(m.set('quarter', 2).month(), 4, 'set same quarter'); + assert.equal(m.set('quarter', 3).month(), 7, 'set 3rd quarter'); + assert.equal(m.set('quarter', 1).month(), 1, 'set 1st quarter'); + assert.equal(m.set('quarter', 4).month(), 10, 'set 4th quarter'); + }); + + test('quarter setter programmatic plural', function (assert) { + var m = moment([2014, 4, 11]); + assert.equal(m.set('quarters', 2).month(), 4, 'set same quarter'); + assert.equal(m.set('quarters', 3).month(), 7, 'set 3rd quarter'); + assert.equal(m.set('quarters', 1).month(), 1, 'set 1st quarter'); + assert.equal(m.set('quarters', 4).month(), 10, 'set 4th quarter'); + }); + + test('quarter setter programmatic abbr', function (assert) { + var m = moment([2014, 4, 11]); + assert.equal(m.set('Q', 2).month(), 4, 'set same quarter'); + assert.equal(m.set('Q', 3).month(), 7, 'set 3rd quarter'); + assert.equal(m.set('Q', 1).month(), 1, 'set 1st quarter'); + assert.equal(m.set('Q', 4).month(), 10, 'set 4th quarter'); + }); + + test('quarter setter only month changes', function (assert) { + var m = moment([2014, 4, 11, 1, 2, 3, 4]).quarter(4); + assert.equal(m.year(), 2014, 'keep year'); + assert.equal(m.month(), 10, 'set month'); + assert.equal(m.date(), 11, 'keep date'); + assert.equal(m.hour(), 1, 'keep hour'); + assert.equal(m.minute(), 2, 'keep minutes'); + assert.equal(m.second(), 3, 'keep seconds'); + assert.equal(m.millisecond(), 4, 'keep milliseconds'); + }); + + test('quarter setter bubble to next year', function (assert) { + var m = moment([2014, 4, 11, 1, 2, 3, 4]).quarter(7); + assert.equal(m.year(), 2015, 'year bubbled'); + assert.equal(m.month(), 7, 'set month'); + assert.equal(m.date(), 11, 'keep date'); + assert.equal(m.hour(), 1, 'keep hour'); + assert.equal(m.minute(), 2, 'keep minutes'); + assert.equal(m.second(), 3, 'keep seconds'); + assert.equal(m.millisecond(), 4, 'keep milliseconds'); + }); + + test('quarter diff', function (assert) { + assert.equal(moment('2014-01-01').diff(moment('2014-04-01'), 'quarter'), + -1, 'diff -1 quarter'); + assert.equal(moment('2014-04-01').diff(moment('2014-01-01'), 'quarter'), + 1, 'diff 1 quarter'); + assert.equal(moment('2014-05-01').diff(moment('2014-01-01'), 'quarter'), + 1, 'diff 1 quarter'); + assert.ok(Math.abs((4 / 3) - moment('2014-05-01').diff( + moment('2014-01-01'), 'quarter', true)) < 0.00001, + 'diff 1 1/3 quarter'); + assert.equal(moment('2015-01-01').diff(moment('2014-01-01'), 'quarter'), + 4, 'diff 4 quarters'); + }); + + test('quarter setter bubble to previous year', function (assert) { + var m = moment([2014, 4, 11, 1, 2, 3, 4]).quarter(-3); + assert.equal(m.year(), 2013, 'year bubbled'); + assert.equal(m.month(), 1, 'set month'); + assert.equal(m.date(), 11, 'keep date'); + assert.equal(m.hour(), 1, 'keep hour'); + assert.equal(m.minute(), 2, 'keep minutes'); + assert.equal(m.second(), 3, 'keep seconds'); + assert.equal(m.millisecond(), 4, 'keep milliseconds'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('relative time'); + + test('default thresholds fromNow', function (assert) { + var a = moment(); + + // Seconds to minutes threshold + a.subtract(44, 'seconds'); + assert.equal(a.fromNow(), 'a few seconds ago', 'Below default seconds to minutes threshold'); + a.subtract(1, 'seconds'); + assert.equal(a.fromNow(), 'a minute ago', 'Above default seconds to minutes threshold'); + + // Minutes to hours threshold + a = moment(); + a.subtract(44, 'minutes'); + assert.equal(a.fromNow(), '44 minutes ago', 'Below default minute to hour threshold'); + a.subtract(1, 'minutes'); + assert.equal(a.fromNow(), 'an hour ago', 'Above default minute to hour threshold'); + + // Hours to days threshold + a = moment(); + a.subtract(21, 'hours'); + assert.equal(a.fromNow(), '21 hours ago', 'Below default hours to day threshold'); + a.subtract(1, 'hours'); + assert.equal(a.fromNow(), 'a day ago', 'Above default hours to day threshold'); + + // Days to month threshold + a = moment(); + a.subtract(25, 'days'); + assert.equal(a.fromNow(), '25 days ago', 'Below default days to month (singular) threshold'); + a.subtract(1, 'days'); + assert.equal(a.fromNow(), 'a month ago', 'Above default days to month (singular) threshold'); + + // months to year threshold + a = moment(); + a.subtract(10, 'months'); + assert.equal(a.fromNow(), '10 months ago', 'Below default days to years threshold'); + a.subtract(1, 'month'); + assert.equal(a.fromNow(), 'a year ago', 'Above default days to years threshold'); + }); + + test('default thresholds toNow', function (assert) { + var a = moment(); + + // Seconds to minutes threshold + a.subtract(44, 'seconds'); + assert.equal(a.toNow(), 'in a few seconds', 'Below default seconds to minutes threshold'); + a.subtract(1, 'seconds'); + assert.equal(a.toNow(), 'in a minute', 'Above default seconds to minutes threshold'); + + // Minutes to hours threshold + a = moment(); + a.subtract(44, 'minutes'); + assert.equal(a.toNow(), 'in 44 minutes', 'Below default minute to hour threshold'); + a.subtract(1, 'minutes'); + assert.equal(a.toNow(), 'in an hour', 'Above default minute to hour threshold'); + + // Hours to days threshold + a = moment(); + a.subtract(21, 'hours'); + assert.equal(a.toNow(), 'in 21 hours', 'Below default hours to day threshold'); + a.subtract(1, 'hours'); + assert.equal(a.toNow(), 'in a day', 'Above default hours to day threshold'); + + // Days to month threshold + a = moment(); + a.subtract(25, 'days'); + assert.equal(a.toNow(), 'in 25 days', 'Below default days to month (singular) threshold'); + a.subtract(1, 'days'); + assert.equal(a.toNow(), 'in a month', 'Above default days to month (singular) threshold'); + + // months to year threshold + a = moment(); + a.subtract(10, 'months'); + assert.equal(a.toNow(), 'in 10 months', 'Below default days to years threshold'); + a.subtract(1, 'month'); + assert.equal(a.toNow(), 'in a year', 'Above default days to years threshold'); + }); + + test('custom thresholds', function (assert) { + // Seconds to minutes threshold + moment.relativeTimeThreshold('s', 55); + + var a = moment(); + a.subtract(54, 'seconds'); + assert.equal(a.fromNow(), 'a few seconds ago', 'Below custom seconds to minutes threshold'); + a.subtract(1, 'seconds'); + assert.equal(a.fromNow(), 'a minute ago', 'Above custom seconds to minutes threshold'); + + moment.relativeTimeThreshold('s', 45); + + // Minutes to hours threshold + moment.relativeTimeThreshold('m', 55); + a = moment(); + a.subtract(54, 'minutes'); + assert.equal(a.fromNow(), '54 minutes ago', 'Below custom minutes to hours threshold'); + a.subtract(1, 'minutes'); + assert.equal(a.fromNow(), 'an hour ago', 'Above custom minutes to hours threshold'); + moment.relativeTimeThreshold('m', 45); + + // Hours to days threshold + moment.relativeTimeThreshold('h', 24); + a = moment(); + a.subtract(23, 'hours'); + assert.equal(a.fromNow(), '23 hours ago', 'Below custom hours to days threshold'); + a.subtract(1, 'hours'); + assert.equal(a.fromNow(), 'a day ago', 'Above custom hours to days threshold'); + moment.relativeTimeThreshold('h', 22); + + // Days to month threshold + moment.relativeTimeThreshold('d', 28); + a = moment(); + a.subtract(27, 'days'); + assert.equal(a.fromNow(), '27 days ago', 'Below custom days to month (singular) threshold'); + a.subtract(1, 'days'); + assert.equal(a.fromNow(), 'a month ago', 'Above custom days to month (singular) threshold'); + moment.relativeTimeThreshold('d', 26); + + // months to years threshold + moment.relativeTimeThreshold('M', 9); + a = moment(); + a.subtract(8, 'months'); + assert.equal(a.fromNow(), '8 months ago', 'Below custom days to years threshold'); + a.subtract(1, 'months'); + assert.equal(a.fromNow(), 'a year ago', 'Above custom days to years threshold'); + moment.relativeTimeThreshold('M', 11); + }); + + test('retrive threshold settings', function (assert) { + moment.relativeTimeThreshold('m', 45); + var minuteThreshold = moment.relativeTimeThreshold('m'); + + assert.equal(minuteThreshold, 45, 'Can retrieve minute setting'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('start and end of units'); + + test('start of year', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('year'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('years'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('y'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 0, 'strip out the month'); + assert.equal(m.date(), 1, 'strip out the day'); + assert.equal(m.hours(), 0, 'strip out the hours'); + assert.equal(m.minutes(), 0, 'strip out the minutes'); + assert.equal(m.seconds(), 0, 'strip out the seconds'); + assert.equal(m.milliseconds(), 0, 'strip out the milliseconds'); + }); + + test('end of year', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('year'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('years'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('y'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 11, 'set the month'); + assert.equal(m.date(), 31, 'set the day'); + assert.equal(m.hours(), 23, 'set the hours'); + assert.equal(m.minutes(), 59, 'set the minutes'); + assert.equal(m.seconds(), 59, 'set the seconds'); + assert.equal(m.milliseconds(), 999, 'set the seconds'); + }); + + test('start of quarter', function (assert) { + var m = moment(new Date(2011, 4, 2, 3, 4, 5, 6)).startOf('quarter'), + ms = moment(new Date(2011, 4, 2, 3, 4, 5, 6)).startOf('quarters'), + ma = moment(new Date(2011, 4, 2, 3, 4, 5, 6)).startOf('Q'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.quarter(), 2, 'keep the quarter'); + assert.equal(m.month(), 3, 'strip out the month'); + assert.equal(m.date(), 1, 'strip out the day'); + assert.equal(m.hours(), 0, 'strip out the hours'); + assert.equal(m.minutes(), 0, 'strip out the minutes'); + assert.equal(m.seconds(), 0, 'strip out the seconds'); + assert.equal(m.milliseconds(), 0, 'strip out the milliseconds'); + }); + + test('end of quarter', function (assert) { + var m = moment(new Date(2011, 4, 2, 3, 4, 5, 6)).endOf('quarter'), + ms = moment(new Date(2011, 4, 2, 3, 4, 5, 6)).endOf('quarters'), + ma = moment(new Date(2011, 4, 2, 3, 4, 5, 6)).endOf('Q'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.quarter(), 2, 'keep the quarter'); + assert.equal(m.month(), 5, 'set the month'); + assert.equal(m.date(), 30, 'set the day'); + assert.equal(m.hours(), 23, 'set the hours'); + assert.equal(m.minutes(), 59, 'set the minutes'); + assert.equal(m.seconds(), 59, 'set the seconds'); + assert.equal(m.milliseconds(), 999, 'set the seconds'); + }); + + test('start of month', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('month'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('months'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('M'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 1, 'keep the month'); + assert.equal(m.date(), 1, 'strip out the day'); + assert.equal(m.hours(), 0, 'strip out the hours'); + assert.equal(m.minutes(), 0, 'strip out the minutes'); + assert.equal(m.seconds(), 0, 'strip out the seconds'); + assert.equal(m.milliseconds(), 0, 'strip out the milliseconds'); + }); + + test('end of month', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('month'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('months'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('M'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 1, 'keep the month'); + assert.equal(m.date(), 28, 'set the day'); + assert.equal(m.hours(), 23, 'set the hours'); + assert.equal(m.minutes(), 59, 'set the minutes'); + assert.equal(m.seconds(), 59, 'set the seconds'); + assert.equal(m.milliseconds(), 999, 'set the seconds'); + }); + + test('start of week', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('week'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('weeks'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('w'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 0, 'rolls back to January'); + assert.equal(m.day(), 0, 'set day of week'); + assert.equal(m.date(), 30, 'set correct date'); + assert.equal(m.hours(), 0, 'strip out the hours'); + assert.equal(m.minutes(), 0, 'strip out the minutes'); + assert.equal(m.seconds(), 0, 'strip out the seconds'); + assert.equal(m.milliseconds(), 0, 'strip out the milliseconds'); + }); + + test('end of week', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('week'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('weeks'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('weeks'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 1, 'keep the month'); + assert.equal(m.day(), 6, 'set the day of the week'); + assert.equal(m.date(), 5, 'set the day'); + assert.equal(m.hours(), 23, 'set the hours'); + assert.equal(m.minutes(), 59, 'set the minutes'); + assert.equal(m.seconds(), 59, 'set the seconds'); + assert.equal(m.milliseconds(), 999, 'set the seconds'); + }); + + test('start of iso-week', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('isoWeek'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('isoWeeks'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('W'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 0, 'rollback to January'); + assert.equal(m.isoWeekday(), 1, 'set day of iso-week'); + assert.equal(m.date(), 31, 'set correct date'); + assert.equal(m.hours(), 0, 'strip out the hours'); + assert.equal(m.minutes(), 0, 'strip out the minutes'); + assert.equal(m.seconds(), 0, 'strip out the seconds'); + assert.equal(m.milliseconds(), 0, 'strip out the milliseconds'); + }); + + test('end of iso-week', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('isoWeek'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('isoWeeks'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('W'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 1, 'keep the month'); + assert.equal(m.isoWeekday(), 7, 'set the day of the week'); + assert.equal(m.date(), 6, 'set the day'); + assert.equal(m.hours(), 23, 'set the hours'); + assert.equal(m.minutes(), 59, 'set the minutes'); + assert.equal(m.seconds(), 59, 'set the seconds'); + assert.equal(m.milliseconds(), 999, 'set the seconds'); + }); + + test('start of day', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('day'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('days'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('d'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 1, 'keep the month'); + assert.equal(m.date(), 2, 'keep the day'); + assert.equal(m.hours(), 0, 'strip out the hours'); + assert.equal(m.minutes(), 0, 'strip out the minutes'); + assert.equal(m.seconds(), 0, 'strip out the seconds'); + assert.equal(m.milliseconds(), 0, 'strip out the milliseconds'); + }); + + test('end of day', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('day'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('days'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('d'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 1, 'keep the month'); + assert.equal(m.date(), 2, 'keep the day'); + assert.equal(m.hours(), 23, 'set the hours'); + assert.equal(m.minutes(), 59, 'set the minutes'); + assert.equal(m.seconds(), 59, 'set the seconds'); + assert.equal(m.milliseconds(), 999, 'set the seconds'); + }); + + test('start of hour', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('hour'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('hours'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('h'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 1, 'keep the month'); + assert.equal(m.date(), 2, 'keep the day'); + assert.equal(m.hours(), 3, 'keep the hours'); + assert.equal(m.minutes(), 0, 'strip out the minutes'); + assert.equal(m.seconds(), 0, 'strip out the seconds'); + assert.equal(m.milliseconds(), 0, 'strip out the milliseconds'); + }); + + test('end of hour', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('hour'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('hours'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('h'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 1, 'keep the month'); + assert.equal(m.date(), 2, 'keep the day'); + assert.equal(m.hours(), 3, 'keep the hours'); + assert.equal(m.minutes(), 59, 'set the minutes'); + assert.equal(m.seconds(), 59, 'set the seconds'); + assert.equal(m.milliseconds(), 999, 'set the seconds'); + }); + + test('start of minute', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('minute'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('minutes'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('m'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 1, 'keep the month'); + assert.equal(m.date(), 2, 'keep the day'); + assert.equal(m.hours(), 3, 'keep the hours'); + assert.equal(m.minutes(), 4, 'keep the minutes'); + assert.equal(m.seconds(), 0, 'strip out the seconds'); + assert.equal(m.milliseconds(), 0, 'strip out the milliseconds'); + }); + + test('end of minute', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('minute'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('minutes'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('m'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 1, 'keep the month'); + assert.equal(m.date(), 2, 'keep the day'); + assert.equal(m.hours(), 3, 'keep the hours'); + assert.equal(m.minutes(), 4, 'keep the minutes'); + assert.equal(m.seconds(), 59, 'set the seconds'); + assert.equal(m.milliseconds(), 999, 'set the seconds'); + }); + + test('start of second', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('second'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('seconds'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).startOf('s'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 1, 'keep the month'); + assert.equal(m.date(), 2, 'keep the day'); + assert.equal(m.hours(), 3, 'keep the hours'); + assert.equal(m.minutes(), 4, 'keep the minutes'); + assert.equal(m.seconds(), 5, 'keep the the seconds'); + assert.equal(m.milliseconds(), 0, 'strip out the milliseconds'); + }); + + test('end of second', function (assert) { + var m = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('second'), + ms = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('seconds'), + ma = moment(new Date(2011, 1, 2, 3, 4, 5, 6)).endOf('s'); + assert.equal(+m, +ms, 'Plural or singular should work'); + assert.equal(+m, +ma, 'Full or abbreviated should work'); + assert.equal(m.year(), 2011, 'keep the year'); + assert.equal(m.month(), 1, 'keep the month'); + assert.equal(m.date(), 2, 'keep the day'); + assert.equal(m.hours(), 3, 'keep the hours'); + assert.equal(m.minutes(), 4, 'keep the minutes'); + assert.equal(m.seconds(), 5, 'keep the seconds'); + assert.equal(m.milliseconds(), 999, 'set the seconds'); + }); + + test('startOf across DST +1', function (assert) { + var oldUpdateOffset = moment.updateOffset, + // Based on a real story somewhere in America/Los_Angeles + dstAt = moment('2014-03-09T02:00:00-08:00').parseZone(), + m; + + moment.updateOffset = function (mom, keepTime) { + if (mom.isBefore(dstAt)) { + mom.utcOffset(-8, keepTime); + } else { + mom.utcOffset(-7, keepTime); + } + }; + + m = moment('2014-03-15T00:00:00-07:00').parseZone(); + m.startOf('M'); + assert.equal(m.format(), '2014-03-01T00:00:00-08:00', 'startOf(\'month\') across +1'); + + m = moment('2014-03-09T09:00:00-07:00').parseZone(); + m.startOf('d'); + assert.equal(m.format(), '2014-03-09T00:00:00-08:00', 'startOf(\'day\') across +1'); + + m = moment('2014-03-09T03:05:00-07:00').parseZone(); + m.startOf('h'); + assert.equal(m.format(), '2014-03-09T03:00:00-07:00', 'startOf(\'hour\') after +1'); + + m = moment('2014-03-09T01:35:00-08:00').parseZone(); + m.startOf('h'); + assert.equal(m.format(), '2014-03-09T01:00:00-08:00', 'startOf(\'hour\') before +1'); + + // There is no such time as 2:30-7 to try startOf('hour') across that + + moment.updateOffset = oldUpdateOffset; + }); + + test('startOf across DST -1', function (assert) { + var oldUpdateOffset = moment.updateOffset, + // Based on a real story somewhere in America/Los_Angeles + dstAt = moment('2014-11-02T02:00:00-07:00').parseZone(), + m; + + moment.updateOffset = function (mom, keepTime) { + if (mom.isBefore(dstAt)) { + mom.utcOffset(-7, keepTime); + } else { + mom.utcOffset(-8, keepTime); + } + }; + + m = moment('2014-11-15T00:00:00-08:00').parseZone(); + m.startOf('M'); + assert.equal(m.format(), '2014-11-01T00:00:00-07:00', 'startOf(\'month\') across -1'); + + m = moment('2014-11-02T09:00:00-08:00').parseZone(); + m.startOf('d'); + assert.equal(m.format(), '2014-11-02T00:00:00-07:00', 'startOf(\'day\') across -1'); + + // note that utc offset is -8 + m = moment('2014-11-02T01:30:00-08:00').parseZone(); + m.startOf('h'); + assert.equal(m.format(), '2014-11-02T01:00:00-08:00', 'startOf(\'hour\') after +1'); + + // note that utc offset is -7 + m = moment('2014-11-02T01:30:00-07:00').parseZone(); + m.startOf('h'); + assert.equal(m.format(), '2014-11-02T01:00:00-07:00', 'startOf(\'hour\') before +1'); + + moment.updateOffset = oldUpdateOffset; + }); + + test('endOf millisecond and no-arg', function (assert) { + var m = moment(); + assert.equal(+m, +m.clone().endOf(), 'endOf without argument should change time'); + assert.equal(+m, +m.clone().endOf('ms'), 'endOf with ms argument should change time'); + assert.equal(+m, +m.clone().endOf('millisecond'), 'endOf with millisecond argument should change time'); + assert.equal(+m, +m.clone().endOf('milliseconds'), 'endOf with milliseconds argument should change time'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('string prototype'); + + test('string prototype overrides call', function (assert) { + var prior = String.prototype.call, b; + String.prototype.call = function () { + return null; + }; + + b = moment(new Date(2011, 7, 28, 15, 25, 50, 125)); + assert.equal(b.format('MMMM Do YYYY, h:mm a'), 'August 28th 2011, 3:25 pm'); + + String.prototype.call = prior; + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('utc'); + + test('utc and local', function (assert) { + var m = moment(Date.UTC(2011, 1, 2, 3, 4, 5, 6)), offset, expected; + m.utc(); + // utc + assert.equal(m.date(), 2, 'the day should be correct for utc'); + assert.equal(m.day(), 3, 'the date should be correct for utc'); + assert.equal(m.hours(), 3, 'the hours should be correct for utc'); + + // local + m.local(); + if (m.zone() > 180) { + assert.equal(m.date(), 1, 'the date should be correct for local'); + assert.equal(m.day(), 2, 'the day should be correct for local'); + } else { + assert.equal(m.date(), 2, 'the date should be correct for local'); + assert.equal(m.day(), 3, 'the day should be correct for local'); + } + offset = Math.ceil(m.utcOffset() / 60); + expected = (24 + 3 + offset) % 24; + assert.equal(m.hours(), expected, 'the hours (' + m.hours() + ') should be correct for local'); + assert.equal(moment().utc().utcOffset(), 0, 'timezone in utc should always be zero'); + }); + + test('creating with utc and no arguments', function (assert) { + var startOfTest = new Date().valueOf(), + momentDefaultUtcTime = moment.utc().valueOf(), + afterMomentCreationTime = new Date().valueOf(); + + assert.ok(startOfTest <= momentDefaultUtcTime, 'moment UTC default time should be now, not in the past'); + assert.ok(momentDefaultUtcTime <= afterMomentCreationTime, 'moment UTC default time should be now, not in the future'); + }); + + test('creating with utc and a date parameter array', function (assert) { + var m = moment.utc([2011, 1, 2, 3, 4, 5, 6]); + assert.equal(m.date(), 2, 'the day should be correct for utc array'); + assert.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'); + assert.equal(m.date(), 2, 'the day should be correct for utc parsing format'); + assert.equal(m.hours(), 3, 'the hours should be correct for utc parsing format'); + + m = moment.utc('2011-02-02T03:04:05+00:00'); + assert.equal(m.date(), 2, 'the day should be correct for utc parsing iso'); + assert.equal(m.hours(), 3, 'the hours should be correct for utc parsing iso'); + }); + + test('creating with utc without timezone', function (assert) { + var m = moment.utc('2012-01-02T08:20:00'); + assert.equal(m.date(), 2, 'the day should be correct for utc parse without timezone'); + assert.equal(m.hours(), 8, 'the hours should be correct for utc parse without timezone'); + + m = moment.utc('2012-01-02T08:20:00+09:00'); + assert.equal(m.date(), 1, 'the day should be correct for utc parse with timezone'); + assert.equal(m.hours(), 23, 'the hours should be correct for utc parse with timezone'); + }); + + test('cloning with utc offset', function (assert) { + var m = moment.utc('2012-01-02T08:20:00'); + assert.equal(moment.utc(m)._isUTC, true, 'the local offset should be converted to UTC'); + assert.equal(moment.utc(m.clone().utc())._isUTC, true, 'the local offset should stay in UTC'); + + m.utcOffset(120); + assert.equal(moment.utc(m)._isUTC, true, 'the explicit utc offset should stay in UTC'); + assert.equal(moment.utc(m).utcOffset(), 0, 'the explicit utc offset should have an offset of 0'); + }); + + test('weekday with utc', function (assert) { + assert.equal( + moment('2013-09-15T00:00:00Z').utc().weekday(), // first minute of the day + moment('2013-09-15T23:59:00Z').utc().weekday(), // last minute of the day + 'a UTC-moment\'s .weekday() should not be affected by the local timezone' + ); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('utc offset'); + + test('setter / getter blackbox', function (assert) { + var m = moment([2010]); + + assert.equal(m.clone().utcOffset(0).utcOffset(), 0, 'utcOffset 0'); + + assert.equal(m.clone().utcOffset(1).utcOffset(), 60, 'utcOffset 1 is 60'); + assert.equal(m.clone().utcOffset(60).utcOffset(), 60, 'utcOffset 60'); + assert.equal(m.clone().utcOffset('+01:00').utcOffset(), 60, 'utcOffset +01:00 is 60'); + assert.equal(m.clone().utcOffset('+0100').utcOffset(), 60, 'utcOffset +0100 is 60'); + + assert.equal(m.clone().utcOffset(-1).utcOffset(), -60, 'utcOffset -1 is -60'); + assert.equal(m.clone().utcOffset(-60).utcOffset(), -60, 'utcOffset -60'); + assert.equal(m.clone().utcOffset('-01:00').utcOffset(), -60, 'utcOffset -01:00 is -60'); + assert.equal(m.clone().utcOffset('-0100').utcOffset(), -60, 'utcOffset -0100 is -60'); + + assert.equal(m.clone().utcOffset(1.5).utcOffset(), 90, 'utcOffset 1.5 is 90'); + assert.equal(m.clone().utcOffset(90).utcOffset(), 90, 'utcOffset 1.5 is 90'); + assert.equal(m.clone().utcOffset('+01:30').utcOffset(), 90, 'utcOffset +01:30 is 90'); + assert.equal(m.clone().utcOffset('+0130').utcOffset(), 90, 'utcOffset +0130 is 90'); + + assert.equal(m.clone().utcOffset(-1.5).utcOffset(), -90, 'utcOffset -1.5'); + assert.equal(m.clone().utcOffset(-90).utcOffset(), -90, 'utcOffset -90'); + assert.equal(m.clone().utcOffset('-01:30').utcOffset(), -90, 'utcOffset +01:30 is 90'); + assert.equal(m.clone().utcOffset('-0130').utcOffset(), -90, 'utcOffset +0130 is 90'); + }); + + test('utcOffset shorthand hours -> minutes', function (assert) { + var i; + for (i = -15; i <= 15; ++i) { + assert.equal(moment().utcOffset(i).utcOffset(), i * 60, + '' + i + ' -> ' + i * 60); + } + assert.equal(moment().utcOffset(-16).utcOffset(), -16, '-16 -> -16'); + assert.equal(moment().utcOffset(16).utcOffset(), 16, '16 -> 16'); + }); + + test('isLocal, isUtc, isUtcOffset', function (assert) { + assert.ok(moment().isLocal(), 'moment() creates objects in local time'); + assert.ok(!moment.utc().isLocal(), 'moment.utc creates objects NOT in local time'); + assert.ok(moment.utc().local().isLocal(), 'moment.fn.local() converts to local time'); + assert.ok(!moment().utcOffset(5).isLocal(), 'moment.fn.utcOffset(N) puts objects NOT in local time'); + assert.ok(moment().utcOffset(5).local().isLocal(), 'moment.fn.local() converts to local time'); + + assert.ok(moment.utc().isUtc(), 'moment.utc() creates objects in utc time'); + assert.ok(moment().utcOffset(0).isUtc(), 'utcOffset(0) is equivalent to utc mode'); + assert.ok(!moment().utcOffset(1).isUtc(), 'utcOffset(1) is NOT equivalent to utc mode'); + + assert.ok(!moment().isUtcOffset(), 'moment() creates objects NOT in utc-offset mode'); + assert.ok(moment.utc().isUtcOffset(), 'moment.utc() creates objects in utc-offset mode'); + assert.ok(moment().utcOffset(3).isUtcOffset(), 'utcOffset(N != 0) creates objects in utc-offset mode'); + assert.ok(moment().utcOffset(0).isUtcOffset(), 'utcOffset(0) creates objects in utc-offset mode'); + }); + + test('isUTC', function (assert) { + assert.ok(moment.utc().isUTC(), 'moment.utc() creates objects in utc time'); + assert.ok(moment().utcOffset(0).isUTC(), 'utcOffset(0) is equivalent to utc mode'); + assert.ok(!moment().utcOffset(1).isUTC(), 'utcOffset(1) is NOT equivalent to utc mode'); + }); + + test('change hours when changing the utc offset', function (assert) { + var m = moment.utc([2000, 0, 1, 6]); + assert.equal(m.hour(), 6, 'UTC 6AM should be 6AM at +0000'); + + // sanity check + m.utcOffset(0); + assert.equal(m.hour(), 6, 'UTC 6AM should be 6AM at +0000'); + + m.utcOffset(-60); + assert.equal(m.hour(), 5, 'UTC 6AM should be 5AM at -0100'); + + m.utcOffset(60); + assert.equal(m.hour(), 7, 'UTC 6AM should be 7AM at +0100'); + }); + + test('change minutes when changing the utc offset', function (assert) { + var m = moment.utc([2000, 0, 1, 6, 31]); + + m.utcOffset(0); + assert.equal(m.format('HH:mm'), '06:31', 'UTC 6:31AM should be 6:31AM at +0000'); + + m.utcOffset(-30); + assert.equal(m.format('HH:mm'), '06:01', 'UTC 6:31AM should be 6:01AM at -0030'); + + m.utcOffset(30); + assert.equal(m.format('HH:mm'), '07:01', 'UTC 6:31AM should be 7:01AM at +0030'); + + m.utcOffset(-1380); + assert.equal(m.format('HH:mm'), '07:31', 'UTC 6:31AM should be 7:31AM at +1380'); + }); + + test('distance from the unix epoch', function (assert) { + var zoneA = moment(), + zoneB = moment(zoneA), + zoneC = moment(zoneA), + zoneD = moment(zoneA), + zoneE = moment(zoneA); + + zoneB.utc(); + assert.equal(+zoneA, +zoneB, 'moment should equal moment.utc'); + + zoneC.utcOffset(60); + assert.equal(+zoneA, +zoneC, 'moment should equal moment.utcOffset(60)'); + + zoneD.utcOffset(-480); + assert.equal(+zoneA, +zoneD, + 'moment should equal moment.utcOffset(-480)'); + + zoneE.utcOffset(-1000); + assert.equal(+zoneA, +zoneE, + 'moment should equal moment.utcOffset(-1000)'); + }); + + test('update offset after changing any values', function (assert) { + var oldOffset = moment.updateOffset, + m = moment.utc([2000, 6, 1]); + + moment.updateOffset = function (mom, keepTime) { + if (mom.__doChange) { + if (+mom > 962409600000) { + mom.utcOffset(-120, keepTime); + } else { + mom.utcOffset(-60, keepTime); + } + } + }; + + assert.equal(m.format('ZZ'), '+0000', 'should be at +0000'); + assert.equal(m.format('HH:mm'), '00:00', 'should start 12AM at +0000 timezone'); + + m.__doChange = true; + m.add(1, 'h'); + + assert.equal(m.format('ZZ'), '-0200', 'should be at -0200'); + assert.equal(m.format('HH:mm'), '23:00', '1AM at +0000 should be 11PM at -0200 timezone'); + + m.subtract(1, 'h'); + + assert.equal(m.format('ZZ'), '-0100', 'should be at -0100'); + assert.equal(m.format('HH:mm'), '23:00', '12AM at +0000 should be 11PM at -0100 timezone'); + + moment.updateOffset = oldOffset; + }); + + ////////////////// + test('getters and setters', function (assert) { + var a = moment([2011, 5, 20]); + + assert.equal(a.clone().utcOffset(-120).year(2012).year(), 2012, 'should get and set year correctly'); + assert.equal(a.clone().utcOffset(-120).month(1).month(), 1, 'should get and set month correctly'); + assert.equal(a.clone().utcOffset(-120).date(2).date(), 2, 'should get and set date correctly'); + assert.equal(a.clone().utcOffset(-120).day(1).day(), 1, 'should get and set day correctly'); + assert.equal(a.clone().utcOffset(-120).hour(1).hour(), 1, 'should get and set hour correctly'); + assert.equal(a.clone().utcOffset(-120).minute(1).minute(), 1, 'should get and set minute correctly'); + }); + + test('getters', function (assert) { + var a = moment.utc([2012, 0, 1, 0, 0, 0]); + + assert.equal(a.clone().utcOffset(-120).year(), 2011, 'should get year correctly'); + assert.equal(a.clone().utcOffset(-120).month(), 11, 'should get month correctly'); + assert.equal(a.clone().utcOffset(-120).date(), 31, 'should get date correctly'); + assert.equal(a.clone().utcOffset(-120).hour(), 22, 'should get hour correctly'); + assert.equal(a.clone().utcOffset(-120).minute(), 0, 'should get minute correctly'); + + assert.equal(a.clone().utcOffset(120).year(), 2012, 'should get year correctly'); + assert.equal(a.clone().utcOffset(120).month(), 0, 'should get month correctly'); + assert.equal(a.clone().utcOffset(120).date(), 1, 'should get date correctly'); + assert.equal(a.clone().utcOffset(120).hour(), 2, 'should get hour correctly'); + assert.equal(a.clone().utcOffset(120).minute(), 0, 'should get minute correctly'); + + assert.equal(a.clone().utcOffset(90).year(), 2012, 'should get year correctly'); + assert.equal(a.clone().utcOffset(90).month(), 0, 'should get month correctly'); + assert.equal(a.clone().utcOffset(90).date(), 1, 'should get date correctly'); + assert.equal(a.clone().utcOffset(90).hour(), 1, 'should get hour correctly'); + assert.equal(a.clone().utcOffset(90).minute(), 30, 'should get minute correctly'); + }); + + test('from', function (assert) { + var zoneA = moment(), + zoneB = moment(zoneA).utcOffset(-720), + zoneC = moment(zoneA).utcOffset(-360), + zoneD = moment(zoneA).utcOffset(690), + other = moment(zoneA).add(35, 'm'); + + assert.equal(zoneA.from(other), zoneB.from(other), 'moment#from should be the same in all zones'); + assert.equal(zoneA.from(other), zoneC.from(other), 'moment#from should be the same in all zones'); + assert.equal(zoneA.from(other), zoneD.from(other), 'moment#from should be the same in all zones'); + }); + + test('diff', function (assert) { + var zoneA = moment(), + zoneB = moment(zoneA).utcOffset(-720), + zoneC = moment(zoneA).utcOffset(-360), + zoneD = moment(zoneA).utcOffset(690), + other = moment(zoneA).add(35, 'm'); + + assert.equal(zoneA.diff(other), zoneB.diff(other), 'moment#diff should be the same in all zones'); + assert.equal(zoneA.diff(other), zoneC.diff(other), 'moment#diff should be the same in all zones'); + assert.equal(zoneA.diff(other), zoneD.diff(other), 'moment#diff should be the same in all zones'); + + assert.equal(zoneA.diff(other, 'minute', true), zoneB.diff(other, 'minute', true), 'moment#diff should be the same in all zones'); + assert.equal(zoneA.diff(other, 'minute', true), zoneC.diff(other, 'minute', true), 'moment#diff should be the same in all zones'); + assert.equal(zoneA.diff(other, 'minute', true), zoneD.diff(other, 'minute', true), 'moment#diff should be the same in all zones'); + + assert.equal(zoneA.diff(other, 'hour', true), zoneB.diff(other, 'hour', true), 'moment#diff should be the same in all zones'); + assert.equal(zoneA.diff(other, 'hour', true), zoneC.diff(other, 'hour', true), 'moment#diff should be the same in all zones'); + assert.equal(zoneA.diff(other, 'hour', true), zoneD.diff(other, 'hour', true), 'moment#diff should be the same in all zones'); + }); + + test('unix offset and timestamp', function (assert) { + var zoneA = moment(), + zoneB = moment(zoneA).utcOffset(-720), + zoneC = moment(zoneA).utcOffset(-360), + zoneD = moment(zoneA).utcOffset(690); + + assert.equal(zoneA.unix(), zoneB.unix(), 'moment#unix should be the same in all zones'); + assert.equal(zoneA.unix(), zoneC.unix(), 'moment#unix should be the same in all zones'); + assert.equal(zoneA.unix(), zoneD.unix(), 'moment#unix should be the same in all zones'); + + assert.equal(+zoneA, +zoneB, 'moment#valueOf should be the same in all zones'); + assert.equal(+zoneA, +zoneC, 'moment#valueOf should be the same in all zones'); + assert.equal(+zoneA, +zoneD, 'moment#valueOf should be the same in all zones'); + }); + + test('cloning', function (assert) { + assert.equal(moment().utcOffset(-120).clone().utcOffset(), -120, + 'explicit cloning should retain the offset'); + assert.equal(moment().utcOffset(120).clone().utcOffset(), 120, + 'explicit cloning should retain the offset'); + assert.equal(moment(moment().utcOffset(-120)).utcOffset(), -120, + 'implicit cloning should retain the offset'); + assert.equal(moment(moment().utcOffset(120)).utcOffset(), 120, + 'implicit cloning should retain the offset'); + }); + + test('start of / end of', function (assert) { + var a = moment.utc([2010, 1, 2, 0, 0, 0]).utcOffset(-450); + + assert.equal(a.clone().startOf('day').hour(), 0, + 'start of day should work on moments with utc offset'); + assert.equal(a.clone().startOf('day').minute(), 0, + 'start of day should work on moments with utc offset'); + assert.equal(a.clone().startOf('hour').minute(), 0, + 'start of hour should work on moments with utc offset'); + + assert.equal(a.clone().endOf('day').hour(), 23, + 'end of day should work on moments with utc offset'); + assert.equal(a.clone().endOf('day').minute(), 59, + 'end of day should work on moments with utc offset'); + assert.equal(a.clone().endOf('hour').minute(), 59, + 'end of hour should work on moments with utc offset'); + }); + + test('reset offset with moment#utc', function (assert) { + var a = moment.utc([2012]).utcOffset(-480); + + assert.equal(a.clone().hour(), 16, 'different utc offset should have different hour'); + assert.equal(a.clone().utc().hour(), 0, 'calling moment#utc should reset the offset'); + }); + + test('reset offset with moment#local', function (assert) { + var a = moment([2012]).utcOffset(-480); + + assert.equal(a.clone().local().hour(), 0, 'calling moment#local should reset the offset'); + }); + + test('toDate', function (assert) { + var zoneA = new Date(), + zoneB = moment(zoneA).utcOffset(-720).toDate(), + zoneC = moment(zoneA).utcOffset(-360).toDate(), + zoneD = moment(zoneA).utcOffset(690).toDate(); + + assert.equal(+zoneA, +zoneB, 'moment#toDate should output a date with the right unix timestamp'); + assert.equal(+zoneA, +zoneC, 'moment#toDate should output a date with the right unix timestamp'); + assert.equal(+zoneA, +zoneD, 'moment#toDate should output a date with the right unix timestamp'); + }); + + test('same / before / after', function (assert) { + var zoneA = moment().utc(), + zoneB = moment(zoneA).utcOffset(-120), + zoneC = moment(zoneA).utcOffset(120); + + assert.ok(zoneA.isSame(zoneB), 'two moments with different offsets should be the same'); + assert.ok(zoneA.isSame(zoneC), 'two moments with different offsets should be the same'); + + assert.ok(zoneA.isSame(zoneB, 'hour'), 'two moments with different offsets should be the same hour'); + assert.ok(zoneA.isSame(zoneC, 'hour'), 'two moments with different offsets should be the same hour'); + + zoneA.add(1, 'hour'); + + assert.ok(zoneA.isAfter(zoneB), 'isAfter should work with two moments with different offsets'); + assert.ok(zoneA.isAfter(zoneC), 'isAfter should work with two moments with different offsets'); + + assert.ok(zoneA.isAfter(zoneB, 'hour'), 'isAfter:hour should work with two moments with different offsets'); + assert.ok(zoneA.isAfter(zoneC, 'hour'), 'isAfter:hour should work with two moments with different offsets'); + + zoneA.subtract(2, 'hour'); + + assert.ok(zoneA.isBefore(zoneB), 'isBefore should work with two moments with different offsets'); + assert.ok(zoneA.isBefore(zoneC), 'isBefore should work with two moments with different offsets'); + + assert.ok(zoneA.isBefore(zoneB, 'hour'), 'isBefore:hour should work with two moments with different offsets'); + assert.ok(zoneA.isBefore(zoneC, 'hour'), 'isBefore:hour should work with two moments with different offsets'); + }); + + test('add / subtract over dst', function (assert) { + var oldOffset = moment.updateOffset, + m = moment.utc([2000, 2, 31, 3]); + + moment.updateOffset = function (mom, keepTime) { + if (mom.clone().utc().month() > 2) { + mom.utcOffset(60, keepTime); + } else { + mom.utcOffset(0, keepTime); + } + }; + + assert.equal(m.hour(), 3, 'should start at 00:00'); + + m.add(24, 'hour'); + + assert.equal(m.hour(), 4, 'adding 24 hours should disregard dst'); + + m.subtract(24, 'hour'); + + assert.equal(m.hour(), 3, 'subtracting 24 hours should disregard dst'); + + m.add(1, 'day'); + + assert.equal(m.hour(), 3, 'adding 1 day should have the same hour'); + + m.subtract(1, 'day'); + + assert.equal(m.hour(), 3, 'subtracting 1 day should have the same hour'); + + m.add(1, 'month'); + + assert.equal(m.hour(), 3, 'adding 1 month should have the same hour'); + + m.subtract(1, 'month'); + + assert.equal(m.hour(), 3, 'subtracting 1 month should have the same hour'); + + moment.updateOffset = oldOffset; + }); + + test('isDST', function (assert) { + var oldOffset = moment.updateOffset; + + moment.updateOffset = function (mom, keepTime) { + if (mom.month() > 2 && mom.month() < 9) { + mom.utcOffset(60, keepTime); + } else { + mom.utcOffset(0, keepTime); + } + }; + + assert.ok(!moment().month(0).isDST(), 'Jan should not be summer dst'); + assert.ok(moment().month(6).isDST(), 'Jul should be summer dst'); + assert.ok(!moment().month(11).isDST(), 'Dec should not be summer dst'); + + moment.updateOffset = function (mom) { + if (mom.month() > 2 && mom.month() < 9) { + mom.utcOffset(0); + } else { + mom.utcOffset(60); + } + }; + + assert.ok(moment().month(0).isDST(), 'Jan should be winter dst'); + assert.ok(!moment().month(6).isDST(), 'Jul should not be winter dst'); + assert.ok(moment().month(11).isDST(), 'Dec should be winter dst'); + + moment.updateOffset = oldOffset; + }); + + test('zone names', function (assert) { + assert.equal(moment().zoneAbbr(), '', 'Local zone abbr should be empty'); + assert.equal(moment().format('z'), '', 'Local zone formatted abbr should be empty'); + assert.equal(moment().zoneName(), '', 'Local zone name should be empty'); + assert.equal(moment().format('zz'), '', 'Local zone formatted name should be empty'); + + assert.equal(moment.utc().zoneAbbr(), 'UTC', 'UTC zone abbr should be UTC'); + assert.equal(moment.utc().format('z'), 'UTC', 'UTC zone formatted abbr should be UTC'); + assert.equal(moment.utc().zoneName(), 'Coordinated Universal Time', 'UTC zone abbr should be Coordinated Universal Time'); + assert.equal(moment.utc().format('zz'), 'Coordinated Universal Time', 'UTC zone formatted abbr should be Coordinated Universal Time'); + }); + + test('hours alignment with UTC', function (assert) { + assert.equal(moment().utcOffset(-120).hasAlignedHourOffset(), true); + assert.equal(moment().utcOffset(180).hasAlignedHourOffset(), true); + assert.equal(moment().utcOffset(-90).hasAlignedHourOffset(), false); + assert.equal(moment().utcOffset(90).hasAlignedHourOffset(), false); + }); + + test('hours alignment with other zone', function (assert) { + var m = moment().utcOffset(-120); + + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(-180)), true); + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(180)), true); + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(-90)), false); + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(90)), false); + + m = moment().utcOffset(-90); + + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(-180)), false); + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(180)), false); + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(-30)), true); + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(30)), true); + + m = moment().utcOffset(60); + + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(-180)), true); + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(180)), true); + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(-90)), false); + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(90)), false); + + m = moment().utcOffset(-25); + + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(35)), true); + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(-85)), true); + + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(-35)), false); + assert.equal(m.hasAlignedHourOffset(moment().utcOffset(85)), false); + }); + + test('parse zone', function (assert) { + var m = moment('2013-01-01T00:00:00-13:00').parseZone(); + assert.equal(m.utcOffset(), -13 * 60); + assert.equal(m.hours(), 0); + }); + + test('parse zone static', function (assert) { + var m = moment.parseZone('2013-01-01T00:00:00-13:00'); + assert.equal(m.utcOffset(), -13 * 60); + assert.equal(m.hours(), 0); + }); + + test('parse zone with more arguments', function (assert) { + var m; + m = moment.parseZone('2013 01 01 05 -13:00', 'YYYY MM DD HH ZZ'); + assert.equal(m.format(), '2013-01-01T05:00:00-13:00', 'accept input and format'); + m = moment.parseZone('2013-01-01-13:00', 'YYYY MM DD ZZ', true); + assert.equal(m.isValid(), false, 'accept input, format and strict flag'); + m = moment.parseZone('2013-01-01-13:00', ['DD MM YYYY ZZ', 'YYYY MM DD ZZ']); + assert.equal(m.format(), '2013-01-01T00:00:00-13:00', 'accept input and array of formats'); + }); + + test('parse zone with a timezone from the format string', function (assert) { + var m = moment('11-12-2013 -0400 +1100', 'DD-MM-YYYY ZZ #####').parseZone(); + + assert.equal(m.utcOffset(), -4 * 60); + }); + + test('parse zone without a timezone included in the format string', function (assert) { + var m = moment('11-12-2013 -0400 +1100', 'DD-MM-YYYY').parseZone(); + + assert.equal(m.utcOffset(), 11 * 60); + }); + + test('timezone format', function (assert) { + assert.equal(moment().utcOffset(60).format('ZZ'), '+0100', '-60 -> +0100'); + assert.equal(moment().utcOffset(90).format('ZZ'), '+0130', '-90 -> +0130'); + assert.equal(moment().utcOffset(120).format('ZZ'), '+0200', '-120 -> +0200'); + + assert.equal(moment().utcOffset(-60).format('ZZ'), '-0100', '+60 -> -0100'); + assert.equal(moment().utcOffset(-90).format('ZZ'), '-0130', '+90 -> -0130'); + assert.equal(moment().utcOffset(-120).format('ZZ'), '-0200', '+120 -> -0200'); + }); + + test('local to utc, keepLocalTime = true', function (assert) { + var m = moment(), + fmt = 'YYYY-DD-MM HH:mm:ss'; + assert.equal(m.clone().utc(true).format(fmt), m.format(fmt), 'local to utc failed to keep local time'); + }); + + test('local to utc, keepLocalTime = false', function (assert) { + var m = moment(); + assert.equal(m.clone().utc().valueOf(), m.valueOf(), 'local to utc failed to keep utc time (implicit)'); + assert.equal(m.clone().utc(false).valueOf(), m.valueOf(), 'local to utc failed to keep utc time (explicit)'); + }); + + test('local to zone, keepLocalTime = true', function (assert) { + var m = moment(), + fmt = 'YYYY-DD-MM HH:mm:ss', + z; + + // Apparently there is -12:00 and +14:00 + // http://en.wikipedia.org/wiki/UTC+14:00 + // http://en.wikipedia.org/wiki/UTC-12:00 + for (z = -12; z <= 14; ++z) { + assert.equal(m.clone().utcOffset(z * 60, true).format(fmt), + m.format(fmt), + 'local to utcOffset(' + z + ':00) failed to keep local time'); + } + }); + + test('local to zone, keepLocalTime = false', function (assert) { + var m = moment(), + z; + + // Apparently there is -12:00 and +14:00 + // http://en.wikipedia.org/wiki/UTC+14:00 + // http://en.wikipedia.org/wiki/UTC-12:00 + for (z = -12; z <= 14; ++z) { + assert.equal(m.clone().utcOffset(z * 60).valueOf(), + m.valueOf(), + 'local to utcOffset(' + z + ':00) failed to keep utc time (implicit)'); + assert.equal(m.clone().utcOffset(z * 60, false).valueOf(), + m.valueOf(), + 'local to utcOffset(' + z + ':00) failed to keep utc time (explicit)'); + } + }); + + test('utc to local, keepLocalTime = true', function (assert) { + var um = moment.utc(), + fmt = 'YYYY-DD-MM HH:mm:ss'; + + assert.equal(um.clone().local(true).format(fmt), um.format(fmt), 'utc to local failed to keep local time'); + }); + + test('utc to local, keepLocalTime = false', function (assert) { + var um = moment.utc(); + assert.equal(um.clone().local().valueOf(), um.valueOf(), 'utc to local failed to keep utc time (implicit)'); + assert.equal(um.clone().local(false).valueOf(), um.valueOf(), 'utc to local failed to keep utc time (explicit)'); + }); + + test('zone to local, keepLocalTime = true', function (assert) { + var m = moment(), + fmt = 'YYYY-DD-MM HH:mm:ss', + z; + + // Apparently there is -12:00 and +14:00 + // http://en.wikipedia.org/wiki/UTC+14:00 + // http://en.wikipedia.org/wiki/UTC-12:00 + for (z = -12; z <= 14; ++z) { + m.utcOffset(z * 60); + + assert.equal(m.clone().local(true).format(fmt), + m.format(fmt), + 'utcOffset(' + z + ':00) to local failed to keep local time'); + } + }); + + test('zone to local, keepLocalTime = false', function (assert) { + var m = moment(), + z; + + // Apparently there is -12:00 and +14:00 + // http://en.wikipedia.org/wiki/UTC+14:00 + // http://en.wikipedia.org/wiki/UTC-12:00 + for (z = -12; z <= 14; ++z) { + m.utcOffset(z * 60); + + assert.equal(m.clone().local(false).valueOf(), m.valueOf(), + 'utcOffset(' + z + ':00) to local failed to keep utc time (explicit)'); + assert.equal(m.clone().local().valueOf(), m.valueOf(), + 'utcOffset(' + z + ':00) to local failed to keep utc time (implicit)'); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('week year'); + + test('iso week year', function (assert) { + // Some examples taken from http://en.wikipedia.org/wiki/ISO_week + assert.equal(moment([2005, 0, 1]).isoWeekYear(), 2004); + assert.equal(moment([2005, 0, 2]).isoWeekYear(), 2004); + assert.equal(moment([2005, 0, 3]).isoWeekYear(), 2005); + assert.equal(moment([2005, 11, 31]).isoWeekYear(), 2005); + assert.equal(moment([2006, 0, 1]).isoWeekYear(), 2005); + assert.equal(moment([2006, 0, 2]).isoWeekYear(), 2006); + assert.equal(moment([2007, 0, 1]).isoWeekYear(), 2007); + assert.equal(moment([2007, 11, 30]).isoWeekYear(), 2007); + assert.equal(moment([2007, 11, 31]).isoWeekYear(), 2008); + assert.equal(moment([2008, 0, 1]).isoWeekYear(), 2008); + assert.equal(moment([2008, 11, 28]).isoWeekYear(), 2008); + assert.equal(moment([2008, 11, 29]).isoWeekYear(), 2009); + assert.equal(moment([2008, 11, 30]).isoWeekYear(), 2009); + assert.equal(moment([2008, 11, 31]).isoWeekYear(), 2009); + assert.equal(moment([2009, 0, 1]).isoWeekYear(), 2009); + assert.equal(moment([2010, 0, 1]).isoWeekYear(), 2009); + assert.equal(moment([2010, 0, 2]).isoWeekYear(), 2009); + assert.equal(moment([2010, 0, 3]).isoWeekYear(), 2009); + assert.equal(moment([2010, 0, 4]).isoWeekYear(), 2010); + }); + + test('week year', function (assert) { + // Some examples taken from http://en.wikipedia.org/wiki/ISO_week + moment.locale('dow: 1,doy: 4', {week: {dow: 1, doy: 4}}); // like iso + assert.equal(moment([2005, 0, 1]).weekYear(), 2004); + assert.equal(moment([2005, 0, 2]).weekYear(), 2004); + assert.equal(moment([2005, 0, 3]).weekYear(), 2005); + assert.equal(moment([2005, 11, 31]).weekYear(), 2005); + assert.equal(moment([2006, 0, 1]).weekYear(), 2005); + assert.equal(moment([2006, 0, 2]).weekYear(), 2006); + assert.equal(moment([2007, 0, 1]).weekYear(), 2007); + assert.equal(moment([2007, 11, 30]).weekYear(), 2007); + assert.equal(moment([2007, 11, 31]).weekYear(), 2008); + assert.equal(moment([2008, 0, 1]).weekYear(), 2008); + assert.equal(moment([2008, 11, 28]).weekYear(), 2008); + assert.equal(moment([2008, 11, 29]).weekYear(), 2009); + assert.equal(moment([2008, 11, 30]).weekYear(), 2009); + assert.equal(moment([2008, 11, 31]).weekYear(), 2009); + assert.equal(moment([2009, 0, 1]).weekYear(), 2009); + assert.equal(moment([2010, 0, 1]).weekYear(), 2009); + assert.equal(moment([2010, 0, 2]).weekYear(), 2009); + assert.equal(moment([2010, 0, 3]).weekYear(), 2009); + assert.equal(moment([2010, 0, 4]).weekYear(), 2010); + + moment.locale('dow: 1,doy: 7', {week: {dow: 1, doy: 7}}); + assert.equal(moment([2004, 11, 26]).weekYear(), 2004); + assert.equal(moment([2004, 11, 27]).weekYear(), 2005); + assert.equal(moment([2005, 11, 25]).weekYear(), 2005); + assert.equal(moment([2005, 11, 26]).weekYear(), 2006); + assert.equal(moment([2006, 11, 31]).weekYear(), 2006); + assert.equal(moment([2007, 0, 1]).weekYear(), 2007); + assert.equal(moment([2007, 11, 30]).weekYear(), 2007); + assert.equal(moment([2007, 11, 31]).weekYear(), 2008); + assert.equal(moment([2008, 11, 28]).weekYear(), 2008); + assert.equal(moment([2008, 11, 29]).weekYear(), 2009); + assert.equal(moment([2009, 11, 27]).weekYear(), 2009); + assert.equal(moment([2009, 11, 28]).weekYear(), 2010); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('week day'); + + test('iso weekday', function (assert) { + var i; + + for (i = 0; i < 7; ++i) { + moment.locale('dow:' + i + ',doy: 6', {week: {dow: i, doy: 6}}); + assert.equal(moment([1985, 1, 4]).isoWeekday(), 1, 'Feb 4 1985 is Monday -- 1st day'); + assert.equal(moment([2029, 8, 18]).isoWeekday(), 2, 'Sep 18 2029 is Tuesday -- 2nd day'); + assert.equal(moment([2013, 3, 24]).isoWeekday(), 3, 'Apr 24 2013 is Wednesday -- 3rd day'); + assert.equal(moment([2015, 2, 5]).isoWeekday(), 4, 'Mar 5 2015 is Thursday -- 4th day'); + assert.equal(moment([1970, 0, 2]).isoWeekday(), 5, 'Jan 2 1970 is Friday -- 5th day'); + assert.equal(moment([2001, 4, 12]).isoWeekday(), 6, 'May 12 2001 is Saturday -- 6th day'); + assert.equal(moment([2000, 0, 2]).isoWeekday(), 7, 'Jan 2 2000 is Sunday -- 7th day'); + } + }); + + test('iso weekday setter', function (assert) { + var a = moment([2011, 0, 10]); + assert.equal(moment(a).isoWeekday(1).date(), 10, 'set from mon to mon'); + assert.equal(moment(a).isoWeekday(4).date(), 13, 'set from mon to thu'); + assert.equal(moment(a).isoWeekday(7).date(), 16, 'set from mon to sun'); + assert.equal(moment(a).isoWeekday(-6).date(), 3, 'set from mon to last mon'); + assert.equal(moment(a).isoWeekday(-3).date(), 6, 'set from mon to last thu'); + assert.equal(moment(a).isoWeekday(0).date(), 9, 'set from mon to last sun'); + assert.equal(moment(a).isoWeekday(8).date(), 17, 'set from mon to next mon'); + assert.equal(moment(a).isoWeekday(11).date(), 20, 'set from mon to next thu'); + assert.equal(moment(a).isoWeekday(14).date(), 23, 'set from mon to next sun'); + + a = moment([2011, 0, 13]); + assert.equal(moment(a).isoWeekday(1).date(), 10, 'set from thu to mon'); + assert.equal(moment(a).isoWeekday(4).date(), 13, 'set from thu to thu'); + assert.equal(moment(a).isoWeekday(7).date(), 16, 'set from thu to sun'); + assert.equal(moment(a).isoWeekday(-6).date(), 3, 'set from thu to last mon'); + assert.equal(moment(a).isoWeekday(-3).date(), 6, 'set from thu to last thu'); + assert.equal(moment(a).isoWeekday(0).date(), 9, 'set from thu to last sun'); + assert.equal(moment(a).isoWeekday(8).date(), 17, 'set from thu to next mon'); + assert.equal(moment(a).isoWeekday(11).date(), 20, 'set from thu to next thu'); + assert.equal(moment(a).isoWeekday(14).date(), 23, 'set from thu to next sun'); + + a = moment([2011, 0, 16]); + assert.equal(moment(a).isoWeekday(1).date(), 10, 'set from sun to mon'); + assert.equal(moment(a).isoWeekday(4).date(), 13, 'set from sun to thu'); + assert.equal(moment(a).isoWeekday(7).date(), 16, 'set from sun to sun'); + assert.equal(moment(a).isoWeekday(-6).date(), 3, 'set from sun to last mon'); + assert.equal(moment(a).isoWeekday(-3).date(), 6, 'set from sun to last thu'); + assert.equal(moment(a).isoWeekday(0).date(), 9, 'set from sun to last sun'); + assert.equal(moment(a).isoWeekday(8).date(), 17, 'set from sun to next mon'); + assert.equal(moment(a).isoWeekday(11).date(), 20, 'set from sun to next thu'); + assert.equal(moment(a).isoWeekday(14).date(), 23, 'set from sun to next sun'); + }); + + test('weekday first day of week Sunday (dow 0)', function (assert) { + moment.locale('dow: 0,doy: 6', {week: {dow: 0, doy: 6}}); + assert.equal(moment([1985, 1, 3]).weekday(), 0, 'Feb 3 1985 is Sunday -- 0th day'); + assert.equal(moment([2029, 8, 17]).weekday(), 1, 'Sep 17 2029 is Monday -- 1st day'); + assert.equal(moment([2013, 3, 23]).weekday(), 2, 'Apr 23 2013 is Tuesday -- 2nd day'); + assert.equal(moment([2015, 2, 4]).weekday(), 3, 'Mar 4 2015 is Wednesday -- 3nd day'); + assert.equal(moment([1970, 0, 1]).weekday(), 4, 'Jan 1 1970 is Thursday -- 4th day'); + assert.equal(moment([2001, 4, 11]).weekday(), 5, 'May 11 2001 is Friday -- 5th day'); + assert.equal(moment([2000, 0, 1]).weekday(), 6, 'Jan 1 2000 is Saturday -- 6th day'); + }); + + test('weekday first day of week Monday (dow 1)', function (assert) { + moment.locale('dow: 1,doy: 6', {week: {dow: 1, doy: 6}}); + assert.equal(moment([1985, 1, 4]).weekday(), 0, 'Feb 4 1985 is Monday -- 0th day'); + assert.equal(moment([2029, 8, 18]).weekday(), 1, 'Sep 18 2029 is Tuesday -- 1st day'); + assert.equal(moment([2013, 3, 24]).weekday(), 2, 'Apr 24 2013 is Wednesday -- 2nd day'); + assert.equal(moment([2015, 2, 5]).weekday(), 3, 'Mar 5 2015 is Thursday -- 3nd day'); + assert.equal(moment([1970, 0, 2]).weekday(), 4, 'Jan 2 1970 is Friday -- 4th day'); + assert.equal(moment([2001, 4, 12]).weekday(), 5, 'May 12 2001 is Saturday -- 5th day'); + assert.equal(moment([2000, 0, 2]).weekday(), 6, 'Jan 2 2000 is Sunday -- 6th day'); + }); + + test('weekday first day of week Tuesday (dow 2)', function (assert) { + moment.locale('dow: 2,doy: 6', {week: {dow: 2, doy: 6}}); + assert.equal(moment([1985, 1, 5]).weekday(), 0, 'Feb 5 1985 is Tuesday -- 0th day'); + assert.equal(moment([2029, 8, 19]).weekday(), 1, 'Sep 19 2029 is Wednesday -- 1st day'); + assert.equal(moment([2013, 3, 25]).weekday(), 2, 'Apr 25 2013 is Thursday -- 2nd day'); + assert.equal(moment([2015, 2, 6]).weekday(), 3, 'Mar 6 2015 is Friday -- 3nd day'); + assert.equal(moment([1970, 0, 3]).weekday(), 4, 'Jan 3 1970 is Staturday -- 4th day'); + assert.equal(moment([2001, 4, 13]).weekday(), 5, 'May 13 2001 is Sunday -- 5th day'); + assert.equal(moment([2000, 0, 3]).weekday(), 6, 'Jan 3 2000 is Monday -- 6th day'); + }); + + test('weekday first day of week Wednesday (dow 3)', function (assert) { + moment.locale('dow: 3,doy: 6', {week: {dow: 3, doy: 6}}); + assert.equal(moment([1985, 1, 6]).weekday(), 0, 'Feb 6 1985 is Wednesday -- 0th day'); + assert.equal(moment([2029, 8, 20]).weekday(), 1, 'Sep 20 2029 is Thursday -- 1st day'); + assert.equal(moment([2013, 3, 26]).weekday(), 2, 'Apr 26 2013 is Friday -- 2nd day'); + assert.equal(moment([2015, 2, 7]).weekday(), 3, 'Mar 7 2015 is Saturday -- 3nd day'); + assert.equal(moment([1970, 0, 4]).weekday(), 4, 'Jan 4 1970 is Sunday -- 4th day'); + assert.equal(moment([2001, 4, 14]).weekday(), 5, 'May 14 2001 is Monday -- 5th day'); + assert.equal(moment([2000, 0, 4]).weekday(), 6, 'Jan 4 2000 is Tuesday -- 6th day'); + moment.locale('dow:3,doy:6', null); + }); + + test('weekday first day of week Thursday (dow 4)', function (assert) { + moment.locale('dow: 4,doy: 6', {week: {dow: 4, doy: 6}}); + assert.equal(moment([1985, 1, 7]).weekday(), 0, 'Feb 7 1985 is Thursday -- 0th day'); + assert.equal(moment([2029, 8, 21]).weekday(), 1, 'Sep 21 2029 is Friday -- 1st day'); + assert.equal(moment([2013, 3, 27]).weekday(), 2, 'Apr 27 2013 is Saturday -- 2nd day'); + assert.equal(moment([2015, 2, 8]).weekday(), 3, 'Mar 8 2015 is Sunday -- 3nd day'); + assert.equal(moment([1970, 0, 5]).weekday(), 4, 'Jan 5 1970 is Monday -- 4th day'); + assert.equal(moment([2001, 4, 15]).weekday(), 5, 'May 15 2001 is Tuesday -- 5th day'); + assert.equal(moment([2000, 0, 5]).weekday(), 6, 'Jan 5 2000 is Wednesday -- 6th day'); + }); + + test('weekday first day of week Friday (dow 5)', function (assert) { + moment.locale('dow: 5,doy: 6', {week: {dow: 5, doy: 6}}); + assert.equal(moment([1985, 1, 8]).weekday(), 0, 'Feb 8 1985 is Friday -- 0th day'); + assert.equal(moment([2029, 8, 22]).weekday(), 1, 'Sep 22 2029 is Staturday -- 1st day'); + assert.equal(moment([2013, 3, 28]).weekday(), 2, 'Apr 28 2013 is Sunday -- 2nd day'); + assert.equal(moment([2015, 2, 9]).weekday(), 3, 'Mar 9 2015 is Monday -- 3nd day'); + assert.equal(moment([1970, 0, 6]).weekday(), 4, 'Jan 6 1970 is Tuesday -- 4th day'); + assert.equal(moment([2001, 4, 16]).weekday(), 5, 'May 16 2001 is Wednesday -- 5th day'); + assert.equal(moment([2000, 0, 6]).weekday(), 6, 'Jan 6 2000 is Thursday -- 6th day'); + }); + + test('weekday first day of week Saturday (dow 6)', function (assert) { + moment.locale('dow: 6,doy: 6', {week: {dow: 6, doy: 6}}); + assert.equal(moment([1985, 1, 9]).weekday(), 0, 'Feb 9 1985 is Staturday -- 0th day'); + assert.equal(moment([2029, 8, 23]).weekday(), 1, 'Sep 23 2029 is Sunday -- 1st day'); + assert.equal(moment([2013, 3, 29]).weekday(), 2, 'Apr 29 2013 is Monday -- 2nd day'); + assert.equal(moment([2015, 2, 10]).weekday(), 3, 'Mar 10 2015 is Tuesday -- 3nd day'); + assert.equal(moment([1970, 0, 7]).weekday(), 4, 'Jan 7 1970 is Wednesday -- 4th day'); + assert.equal(moment([2001, 4, 17]).weekday(), 5, 'May 17 2001 is Thursday -- 5th day'); + assert.equal(moment([2000, 0, 7]).weekday(), 6, 'Jan 7 2000 is Friday -- 6th day'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('weeks'); + + test('day of year', function (assert) { + assert.equal(moment([2000, 0, 1]).dayOfYear(), 1, 'Jan 1 2000 should be day 1 of the year'); + assert.equal(moment([2000, 1, 28]).dayOfYear(), 59, 'Feb 28 2000 should be day 59 of the year'); + assert.equal(moment([2000, 1, 29]).dayOfYear(), 60, 'Feb 28 2000 should be day 60 of the year'); + assert.equal(moment([2000, 11, 31]).dayOfYear(), 366, 'Dec 31 2000 should be day 366 of the year'); + assert.equal(moment([2001, 0, 1]).dayOfYear(), 1, 'Jan 1 2001 should be day 1 of the year'); + assert.equal(moment([2001, 1, 28]).dayOfYear(), 59, 'Feb 28 2001 should be day 59 of the year'); + assert.equal(moment([2001, 2, 1]).dayOfYear(), 60, 'Mar 1 2001 should be day 60 of the year'); + assert.equal(moment([2001, 11, 31]).dayOfYear(), 365, 'Dec 31 2001 should be day 365 of the year'); + }); + + test('day of year setters', function (assert) { + assert.equal(moment([2000, 0, 1]).dayOfYear(200).dayOfYear(), 200, 'Setting Jan 1 2000 day of the year to 200 should work'); + assert.equal(moment([2000, 1, 28]).dayOfYear(200).dayOfYear(), 200, 'Setting Feb 28 2000 day of the year to 200 should work'); + assert.equal(moment([2000, 1, 29]).dayOfYear(200).dayOfYear(), 200, 'Setting Feb 28 2000 day of the year to 200 should work'); + assert.equal(moment([2000, 11, 31]).dayOfYear(200).dayOfYear(), 200, 'Setting Dec 31 2000 day of the year to 200 should work'); + assert.equal(moment().dayOfYear(1).dayOfYear(), 1, 'Setting day of the year to 1 should work'); + assert.equal(moment().dayOfYear(59).dayOfYear(), 59, 'Setting day of the year to 59 should work'); + assert.equal(moment().dayOfYear(60).dayOfYear(), 60, 'Setting day of the year to 60 should work'); + assert.equal(moment().dayOfYear(365).dayOfYear(), 365, 'Setting day of the year to 365 should work'); + }); + + test('iso weeks year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).isoWeek(), 52, 'Jan 1 2012 should be iso week 52'); + assert.equal(moment([2012, 0, 2]).isoWeek(), 1, 'Jan 2 2012 should be iso week 1'); + assert.equal(moment([2012, 0, 8]).isoWeek(), 1, 'Jan 8 2012 should be iso week 1'); + assert.equal(moment([2012, 0, 9]).isoWeek(), 2, 'Jan 9 2012 should be iso week 2'); + assert.equal(moment([2012, 0, 15]).isoWeek(), 2, 'Jan 15 2012 should be iso week 2'); + }); + + test('iso weeks year starting monday', function (assert) { + assert.equal(moment([2007, 0, 1]).isoWeek(), 1, 'Jan 1 2007 should be iso week 1'); + assert.equal(moment([2007, 0, 7]).isoWeek(), 1, 'Jan 7 2007 should be iso week 1'); + assert.equal(moment([2007, 0, 8]).isoWeek(), 2, 'Jan 8 2007 should be iso week 2'); + assert.equal(moment([2007, 0, 14]).isoWeek(), 2, 'Jan 14 2007 should be iso week 2'); + assert.equal(moment([2007, 0, 15]).isoWeek(), 3, 'Jan 15 2007 should be iso week 3'); + }); + + test('iso weeks year starting tuesday', function (assert) { + assert.equal(moment([2007, 11, 31]).isoWeek(), 1, 'Dec 31 2007 should be iso week 1'); + assert.equal(moment([2008, 0, 1]).isoWeek(), 1, 'Jan 1 2008 should be iso week 1'); + assert.equal(moment([2008, 0, 6]).isoWeek(), 1, 'Jan 6 2008 should be iso week 1'); + assert.equal(moment([2008, 0, 7]).isoWeek(), 2, 'Jan 7 2008 should be iso week 2'); + assert.equal(moment([2008, 0, 13]).isoWeek(), 2, 'Jan 13 2008 should be iso week 2'); + assert.equal(moment([2008, 0, 14]).isoWeek(), 3, 'Jan 14 2008 should be iso week 3'); + }); + + test('iso weeks year starting wednesday', function (assert) { + assert.equal(moment([2002, 11, 30]).isoWeek(), 1, 'Dec 30 2002 should be iso week 1'); + assert.equal(moment([2003, 0, 1]).isoWeek(), 1, 'Jan 1 2003 should be iso week 1'); + assert.equal(moment([2003, 0, 5]).isoWeek(), 1, 'Jan 5 2003 should be iso week 1'); + assert.equal(moment([2003, 0, 6]).isoWeek(), 2, 'Jan 6 2003 should be iso week 2'); + assert.equal(moment([2003, 0, 12]).isoWeek(), 2, 'Jan 12 2003 should be iso week 2'); + assert.equal(moment([2003, 0, 13]).isoWeek(), 3, 'Jan 13 2003 should be iso week 3'); + }); + + test('iso weeks year starting thursday', function (assert) { + assert.equal(moment([2008, 11, 29]).isoWeek(), 1, 'Dec 29 2008 should be iso week 1'); + assert.equal(moment([2009, 0, 1]).isoWeek(), 1, 'Jan 1 2009 should be iso week 1'); + assert.equal(moment([2009, 0, 4]).isoWeek(), 1, 'Jan 4 2009 should be iso week 1'); + assert.equal(moment([2009, 0, 5]).isoWeek(), 2, 'Jan 5 2009 should be iso week 2'); + assert.equal(moment([2009, 0, 11]).isoWeek(), 2, 'Jan 11 2009 should be iso week 2'); + assert.equal(moment([2009, 0, 13]).isoWeek(), 3, 'Jan 12 2009 should be iso week 3'); + }); + + test('iso weeks year starting friday', function (assert) { + assert.equal(moment([2009, 11, 28]).isoWeek(), 53, 'Dec 28 2009 should be iso week 53'); + assert.equal(moment([2010, 0, 1]).isoWeek(), 53, 'Jan 1 2010 should be iso week 53'); + assert.equal(moment([2010, 0, 3]).isoWeek(), 53, 'Jan 3 2010 should be iso week 53'); + assert.equal(moment([2010, 0, 4]).isoWeek(), 1, 'Jan 4 2010 should be iso week 1'); + assert.equal(moment([2010, 0, 10]).isoWeek(), 1, 'Jan 10 2010 should be iso week 1'); + assert.equal(moment([2010, 0, 11]).isoWeek(), 2, 'Jan 11 2010 should be iso week 2'); + }); + + test('iso weeks year starting saturday', function (assert) { + assert.equal(moment([2010, 11, 27]).isoWeek(), 52, 'Dec 27 2010 should be iso week 52'); + assert.equal(moment([2011, 0, 1]).isoWeek(), 52, 'Jan 1 2011 should be iso week 52'); + assert.equal(moment([2011, 0, 2]).isoWeek(), 52, 'Jan 2 2011 should be iso week 52'); + assert.equal(moment([2011, 0, 3]).isoWeek(), 1, 'Jan 3 2011 should be iso week 1'); + assert.equal(moment([2011, 0, 9]).isoWeek(), 1, 'Jan 9 2011 should be iso week 1'); + assert.equal(moment([2011, 0, 10]).isoWeek(), 2, 'Jan 10 2011 should be iso week 2'); + }); + + test('iso weeks year starting sunday formatted', function (assert) { + assert.equal(moment([2012, 0, 1]).format('W WW Wo'), '52 52 52nd', 'Jan 1 2012 should be iso week 52'); + assert.equal(moment([2012, 0, 2]).format('W WW Wo'), '1 01 1st', 'Jan 2 2012 should be iso week 1'); + assert.equal(moment([2012, 0, 8]).format('W WW Wo'), '1 01 1st', 'Jan 8 2012 should be iso week 1'); + assert.equal(moment([2012, 0, 9]).format('W WW Wo'), '2 02 2nd', 'Jan 9 2012 should be iso week 2'); + assert.equal(moment([2012, 0, 15]).format('W WW Wo'), '2 02 2nd', 'Jan 15 2012 should be iso week 2'); + }); + + test('weeks plural year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).weeks(), 1, 'Jan 1 2012 should be week 1'); + assert.equal(moment([2012, 0, 7]).weeks(), 1, 'Jan 7 2012 should be week 1'); + assert.equal(moment([2012, 0, 8]).weeks(), 2, 'Jan 8 2012 should be week 2'); + assert.equal(moment([2012, 0, 14]).weeks(), 2, 'Jan 14 2012 should be week 2'); + assert.equal(moment([2012, 0, 15]).weeks(), 3, 'Jan 15 2012 should be week 3'); + }); + + test('iso weeks plural year starting sunday', function (assert) { + assert.equal(moment([2012, 0, 1]).isoWeeks(), 52, 'Jan 1 2012 should be iso week 52'); + assert.equal(moment([2012, 0, 2]).isoWeeks(), 1, 'Jan 2 2012 should be iso week 1'); + assert.equal(moment([2012, 0, 8]).isoWeeks(), 1, 'Jan 8 2012 should be iso week 1'); + assert.equal(moment([2012, 0, 9]).isoWeeks(), 2, 'Jan 9 2012 should be iso week 2'); + assert.equal(moment([2012, 0, 15]).isoWeeks(), 2, 'Jan 15 2012 should be iso week 2'); + }); + + test('weeks setter', function (assert) { + assert.equal(moment([2012, 0, 1]).week(30).week(), 30, 'Setting Jan 1 2012 to week 30 should work'); + assert.equal(moment([2012, 0, 7]).week(30).week(), 30, 'Setting Jan 7 2012 to week 30 should work'); + assert.equal(moment([2012, 0, 8]).week(30).week(), 30, 'Setting Jan 8 2012 to week 30 should work'); + assert.equal(moment([2012, 0, 14]).week(30).week(), 30, 'Setting Jan 14 2012 to week 30 should work'); + assert.equal(moment([2012, 0, 15]).week(30).week(), 30, 'Setting Jan 15 2012 to week 30 should work'); + }); + + test('iso weeks setter', function (assert) { + assert.equal(moment([2012, 0, 1]).isoWeeks(25).isoWeeks(), 25, 'Setting Jan 1 2012 to week 25 should work'); + assert.equal(moment([2012, 0, 2]).isoWeeks(24).isoWeeks(), 24, 'Setting Jan 2 2012 to week 24 should work'); + assert.equal(moment([2012, 0, 8]).isoWeeks(23).isoWeeks(), 23, 'Setting Jan 8 2012 to week 23 should work'); + assert.equal(moment([2012, 0, 9]).isoWeeks(22).isoWeeks(), 22, 'Setting Jan 9 2012 to week 22 should work'); + assert.equal(moment([2012, 0, 15]).isoWeeks(21).isoWeeks(), 21, 'Setting Jan 15 2012 to week 21 should work'); + }); + + test('iso weeks setter day of year', function (assert) { + assert.equal(moment([2012, 0, 1]).isoWeek(1).dayOfYear(), 9, 'Setting Jan 1 2012 to week 1 should be day of year 8'); + assert.equal(moment([2012, 0, 1]).isoWeek(1).year(), 2011, 'Setting Jan 1 2012 to week 1 should be year 2011'); + assert.equal(moment([2012, 0, 2]).isoWeek(1).dayOfYear(), 2, 'Setting Jan 2 2012 to week 1 should be day of year 2'); + assert.equal(moment([2012, 0, 8]).isoWeek(1).dayOfYear(), 8, 'Setting Jan 8 2012 to week 1 should be day of year 8'); + assert.equal(moment([2012, 0, 9]).isoWeek(1).dayOfYear(), 2, 'Setting Jan 9 2012 to week 1 should be day of year 2'); + assert.equal(moment([2012, 0, 15]).isoWeek(1).dayOfYear(), 8, 'Setting Jan 15 2012 to week 1 should be day of year 8'); + }); + + test('years with iso week 53', function (assert) { + // Based on a table taken from http://en.wikipedia.org/wiki/ISO_week_date + // (as downloaded on 2014-01-06) listing the 71 years in a 400-year cycle + // that have 53 weeks; in this case reflecting the 2000 based cycle + assert.equal(moment([2004, 11, 31]).isoWeek(), 53, 'Dec 31 2004 should be iso week 53'); + assert.equal(moment([2009, 11, 31]).isoWeek(), 53, 'Dec 31 2009 should be iso week 53'); + assert.equal(moment([2015, 11, 31]).isoWeek(), 53, 'Dec 31 2015 should be iso week 53'); + assert.equal(moment([2020, 11, 31]).isoWeek(), 53, 'Dec 31 2020 should be iso week 53'); + assert.equal(moment([2026, 11, 31]).isoWeek(), 53, 'Dec 31 2026 should be iso week 53'); + assert.equal(moment([2032, 11, 31]).isoWeek(), 53, 'Dec 31 2032 should be iso week 53'); + assert.equal(moment([2037, 11, 31]).isoWeek(), 53, 'Dec 31 2037 should be iso week 53'); + assert.equal(moment([2043, 11, 31]).isoWeek(), 53, 'Dec 31 2043 should be iso week 53'); + assert.equal(moment([2048, 11, 31]).isoWeek(), 53, 'Dec 31 2048 should be iso week 53'); + assert.equal(moment([2054, 11, 31]).isoWeek(), 53, 'Dec 31 2054 should be iso week 53'); + assert.equal(moment([2060, 11, 31]).isoWeek(), 53, 'Dec 31 2060 should be iso week 53'); + assert.equal(moment([2065, 11, 31]).isoWeek(), 53, 'Dec 31 2065 should be iso week 53'); + assert.equal(moment([2071, 11, 31]).isoWeek(), 53, 'Dec 31 2071 should be iso week 53'); + assert.equal(moment([2076, 11, 31]).isoWeek(), 53, 'Dec 31 2076 should be iso week 53'); + assert.equal(moment([2082, 11, 31]).isoWeek(), 53, 'Dec 31 2082 should be iso week 53'); + assert.equal(moment([2088, 11, 31]).isoWeek(), 53, 'Dec 31 2088 should be iso week 53'); + assert.equal(moment([2093, 11, 31]).isoWeek(), 53, 'Dec 31 2093 should be iso week 53'); + assert.equal(moment([2099, 11, 31]).isoWeek(), 53, 'Dec 31 2099 should be iso week 53'); + assert.equal(moment([2105, 11, 31]).isoWeek(), 53, 'Dec 31 2105 should be iso week 53'); + assert.equal(moment([2111, 11, 31]).isoWeek(), 53, 'Dec 31 2111 should be iso week 53'); + assert.equal(moment([2116, 11, 31]).isoWeek(), 53, 'Dec 31 2116 should be iso week 53'); + assert.equal(moment([2122, 11, 31]).isoWeek(), 53, 'Dec 31 2122 should be iso week 53'); + assert.equal(moment([2128, 11, 31]).isoWeek(), 53, 'Dec 31 2128 should be iso week 53'); + assert.equal(moment([2133, 11, 31]).isoWeek(), 53, 'Dec 31 2133 should be iso week 53'); + assert.equal(moment([2139, 11, 31]).isoWeek(), 53, 'Dec 31 2139 should be iso week 53'); + assert.equal(moment([2144, 11, 31]).isoWeek(), 53, 'Dec 31 2144 should be iso week 53'); + assert.equal(moment([2150, 11, 31]).isoWeek(), 53, 'Dec 31 2150 should be iso week 53'); + assert.equal(moment([2156, 11, 31]).isoWeek(), 53, 'Dec 31 2156 should be iso week 53'); + assert.equal(moment([2161, 11, 31]).isoWeek(), 53, 'Dec 31 2161 should be iso week 53'); + assert.equal(moment([2167, 11, 31]).isoWeek(), 53, 'Dec 31 2167 should be iso week 53'); + assert.equal(moment([2172, 11, 31]).isoWeek(), 53, 'Dec 31 2172 should be iso week 53'); + assert.equal(moment([2178, 11, 31]).isoWeek(), 53, 'Dec 31 2178 should be iso week 53'); + assert.equal(moment([2184, 11, 31]).isoWeek(), 53, 'Dec 31 2184 should be iso week 53'); + assert.equal(moment([2189, 11, 31]).isoWeek(), 53, 'Dec 31 2189 should be iso week 53'); + assert.equal(moment([2195, 11, 31]).isoWeek(), 53, 'Dec 31 2195 should be iso week 53'); + assert.equal(moment([2201, 11, 31]).isoWeek(), 53, 'Dec 31 2201 should be iso week 53'); + assert.equal(moment([2207, 11, 31]).isoWeek(), 53, 'Dec 31 2207 should be iso week 53'); + assert.equal(moment([2212, 11, 31]).isoWeek(), 53, 'Dec 31 2212 should be iso week 53'); + assert.equal(moment([2218, 11, 31]).isoWeek(), 53, 'Dec 31 2218 should be iso week 53'); + assert.equal(moment([2224, 11, 31]).isoWeek(), 53, 'Dec 31 2224 should be iso week 53'); + assert.equal(moment([2229, 11, 31]).isoWeek(), 53, 'Dec 31 2229 should be iso week 53'); + assert.equal(moment([2235, 11, 31]).isoWeek(), 53, 'Dec 31 2235 should be iso week 53'); + assert.equal(moment([2240, 11, 31]).isoWeek(), 53, 'Dec 31 2240 should be iso week 53'); + assert.equal(moment([2246, 11, 31]).isoWeek(), 53, 'Dec 31 2246 should be iso week 53'); + assert.equal(moment([2252, 11, 31]).isoWeek(), 53, 'Dec 31 2252 should be iso week 53'); + assert.equal(moment([2257, 11, 31]).isoWeek(), 53, 'Dec 31 2257 should be iso week 53'); + assert.equal(moment([2263, 11, 31]).isoWeek(), 53, 'Dec 31 2263 should be iso week 53'); + assert.equal(moment([2268, 11, 31]).isoWeek(), 53, 'Dec 31 2268 should be iso week 53'); + assert.equal(moment([2274, 11, 31]).isoWeek(), 53, 'Dec 31 2274 should be iso week 53'); + assert.equal(moment([2280, 11, 31]).isoWeek(), 53, 'Dec 31 2280 should be iso week 53'); + assert.equal(moment([2285, 11, 31]).isoWeek(), 53, 'Dec 31 2285 should be iso week 53'); + assert.equal(moment([2291, 11, 31]).isoWeek(), 53, 'Dec 31 2291 should be iso week 53'); + assert.equal(moment([2296, 11, 31]).isoWeek(), 53, 'Dec 31 2296 should be iso week 53'); + assert.equal(moment([2303, 11, 31]).isoWeek(), 53, 'Dec 31 2303 should be iso week 53'); + assert.equal(moment([2308, 11, 31]).isoWeek(), 53, 'Dec 31 2308 should be iso week 53'); + assert.equal(moment([2314, 11, 31]).isoWeek(), 53, 'Dec 31 2314 should be iso week 53'); + assert.equal(moment([2320, 11, 31]).isoWeek(), 53, 'Dec 31 2320 should be iso week 53'); + assert.equal(moment([2325, 11, 31]).isoWeek(), 53, 'Dec 31 2325 should be iso week 53'); + assert.equal(moment([2331, 11, 31]).isoWeek(), 53, 'Dec 31 2331 should be iso week 53'); + assert.equal(moment([2336, 11, 31]).isoWeek(), 53, 'Dec 31 2336 should be iso week 53'); + assert.equal(moment([2342, 11, 31]).isoWeek(), 53, 'Dec 31 2342 should be iso week 53'); + assert.equal(moment([2348, 11, 31]).isoWeek(), 53, 'Dec 31 2348 should be iso week 53'); + assert.equal(moment([2353, 11, 31]).isoWeek(), 53, 'Dec 31 2353 should be iso week 53'); + assert.equal(moment([2359, 11, 31]).isoWeek(), 53, 'Dec 31 2359 should be iso week 53'); + assert.equal(moment([2364, 11, 31]).isoWeek(), 53, 'Dec 31 2364 should be iso week 53'); + assert.equal(moment([2370, 11, 31]).isoWeek(), 53, 'Dec 31 2370 should be iso week 53'); + assert.equal(moment([2376, 11, 31]).isoWeek(), 53, 'Dec 31 2376 should be iso week 53'); + assert.equal(moment([2381, 11, 31]).isoWeek(), 53, 'Dec 31 2381 should be iso week 53'); + assert.equal(moment([2387, 11, 31]).isoWeek(), 53, 'Dec 31 2387 should be iso week 53'); + assert.equal(moment([2392, 11, 31]).isoWeek(), 53, 'Dec 31 2392 should be iso week 53'); + assert.equal(moment([2398, 11, 31]).isoWeek(), 53, 'Dec 31 2398 should be iso week 53'); + }); + + test('count years with iso week 53', function (assert) { + // Based on http://en.wikipedia.org/wiki/ISO_week_date (as seen on 2014-01-06) + // stating that there are 71 years in a 400-year cycle that have 53 weeks; + // in this case reflecting the 2000 based cycle + var count = 0, i; + for (i = 0; i < 400; i++) { + count += (moment([2000 + i, 11, 31]).isoWeek() === 53) ? 1 : 0; + } + assert.equal(count, 71, 'Should have 71 years in 400-year cycle with iso week 53'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('weeks in year'); + + test('isoWeeksInYear', function (assert) { + assert.equal(moment([2004]).isoWeeksInYear(), 53, '2004 has 53 iso weeks'); + assert.equal(moment([2005]).isoWeeksInYear(), 52, '2005 has 53 iso weeks'); + assert.equal(moment([2006]).isoWeeksInYear(), 52, '2006 has 53 iso weeks'); + assert.equal(moment([2007]).isoWeeksInYear(), 52, '2007 has 52 iso weeks'); + assert.equal(moment([2008]).isoWeeksInYear(), 52, '2008 has 53 iso weeks'); + assert.equal(moment([2009]).isoWeeksInYear(), 53, '2009 has 53 iso weeks'); + assert.equal(moment([2010]).isoWeeksInYear(), 52, '2010 has 52 iso weeks'); + assert.equal(moment([2011]).isoWeeksInYear(), 52, '2011 has 52 iso weeks'); + assert.equal(moment([2012]).isoWeeksInYear(), 52, '2012 has 52 iso weeks'); + assert.equal(moment([2013]).isoWeeksInYear(), 52, '2013 has 52 iso weeks'); + assert.equal(moment([2014]).isoWeeksInYear(), 52, '2014 has 52 iso weeks'); + assert.equal(moment([2015]).isoWeeksInYear(), 53, '2015 has 53 iso weeks'); + }); + + test('weeksInYear doy/dow = 1/4', function (assert) { + moment.locale('1/4', {week: {dow: 1, doy: 4}}); + + assert.equal(moment([2004]).weeksInYear(), 53, '2004 has 53 weeks'); + assert.equal(moment([2005]).weeksInYear(), 52, '2005 has 53 weeks'); + assert.equal(moment([2006]).weeksInYear(), 52, '2006 has 53 weeks'); + assert.equal(moment([2007]).weeksInYear(), 52, '2007 has 52 weeks'); + assert.equal(moment([2008]).weeksInYear(), 52, '2008 has 53 weeks'); + assert.equal(moment([2009]).weeksInYear(), 53, '2009 has 53 weeks'); + assert.equal(moment([2010]).weeksInYear(), 52, '2010 has 52 weeks'); + assert.equal(moment([2011]).weeksInYear(), 52, '2011 has 52 weeks'); + assert.equal(moment([2012]).weeksInYear(), 52, '2012 has 52 weeks'); + assert.equal(moment([2013]).weeksInYear(), 52, '2013 has 52 weeks'); + assert.equal(moment([2014]).weeksInYear(), 52, '2014 has 52 weeks'); + assert.equal(moment([2015]).weeksInYear(), 53, '2015 has 53 weeks'); + }); + + test('weeksInYear doy/dow = 6/12', function (assert) { + moment.locale('6/12', {week: {dow: 6, doy: 12}}); + + assert.equal(moment([2004]).weeksInYear(), 53, '2004 has 53 weeks'); + assert.equal(moment([2005]).weeksInYear(), 52, '2005 has 53 weeks'); + assert.equal(moment([2006]).weeksInYear(), 52, '2006 has 53 weeks'); + assert.equal(moment([2007]).weeksInYear(), 52, '2007 has 52 weeks'); + assert.equal(moment([2008]).weeksInYear(), 52, '2008 has 53 weeks'); + assert.equal(moment([2009]).weeksInYear(), 52, '2009 has 53 weeks'); + assert.equal(moment([2010]).weeksInYear(), 53, '2010 has 52 weeks'); + assert.equal(moment([2011]).weeksInYear(), 52, '2011 has 52 weeks'); + assert.equal(moment([2012]).weeksInYear(), 52, '2012 has 52 weeks'); + assert.equal(moment([2013]).weeksInYear(), 52, '2013 has 52 weeks'); + assert.equal(moment([2014]).weeksInYear(), 52, '2014 has 52 weeks'); + assert.equal(moment([2015]).weeksInYear(), 52, '2015 has 53 weeks'); + }); + + test('weeksInYear doy/dow = 1/7', function (assert) { + moment.locale('1/7', {week: {dow: 1, doy: 7}}); + + assert.equal(moment([2004]).weeksInYear(), 52, '2004 has 53 weeks'); + assert.equal(moment([2005]).weeksInYear(), 52, '2005 has 53 weeks'); + assert.equal(moment([2006]).weeksInYear(), 53, '2006 has 53 weeks'); + assert.equal(moment([2007]).weeksInYear(), 52, '2007 has 52 weeks'); + assert.equal(moment([2008]).weeksInYear(), 52, '2008 has 53 weeks'); + assert.equal(moment([2009]).weeksInYear(), 52, '2009 has 53 weeks'); + assert.equal(moment([2010]).weeksInYear(), 52, '2010 has 52 weeks'); + assert.equal(moment([2011]).weeksInYear(), 52, '2011 has 52 weeks'); + assert.equal(moment([2012]).weeksInYear(), 53, '2012 has 52 weeks'); + assert.equal(moment([2013]).weeksInYear(), 52, '2013 has 52 weeks'); + assert.equal(moment([2014]).weeksInYear(), 52, '2014 has 52 weeks'); + assert.equal(moment([2015]).weeksInYear(), 52, '2015 has 53 weeks'); + }); + + test('weeksInYear doy/dow = 0/6', function (assert) { + moment.locale('0/6', {week: {dow: 0, doy: 6}}); + + assert.equal(moment([2004]).weeksInYear(), 52, '2004 has 53 weeks'); + assert.equal(moment([2005]).weeksInYear(), 53, '2005 has 53 weeks'); + assert.equal(moment([2006]).weeksInYear(), 52, '2006 has 53 weeks'); + assert.equal(moment([2007]).weeksInYear(), 52, '2007 has 52 weeks'); + assert.equal(moment([2008]).weeksInYear(), 52, '2008 has 53 weeks'); + assert.equal(moment([2009]).weeksInYear(), 52, '2009 has 53 weeks'); + assert.equal(moment([2010]).weeksInYear(), 52, '2010 has 52 weeks'); + assert.equal(moment([2011]).weeksInYear(), 53, '2011 has 52 weeks'); + assert.equal(moment([2012]).weeksInYear(), 52, '2012 has 52 weeks'); + assert.equal(moment([2013]).weeksInYear(), 52, '2013 has 52 weeks'); + assert.equal(moment([2014]).weeksInYear(), 52, '2014 has 52 weeks'); + assert.equal(moment([2015]).weeksInYear(), 52, '2015 has 53 weeks'); + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('zone switching'); + + test('local to utc, keepLocalTime = true', function (assert) { + var m = moment(), + fmt = 'YYYY-DD-MM HH:mm:ss'; + assert.equal(m.clone().utc(true).format(fmt), m.format(fmt), 'local to utc failed to keep local time'); + }); + + test('local to utc, keepLocalTime = false', function (assert) { + var m = moment(); + assert.equal(m.clone().utc().valueOf(), m.valueOf(), 'local to utc failed to keep utc time (implicit)'); + assert.equal(m.clone().utc(false).valueOf(), m.valueOf(), 'local to utc failed to keep utc time (explicit)'); + }); + + test('local to zone, keepLocalTime = true', function (assert) { + var m = moment(), + fmt = 'YYYY-DD-MM HH:mm:ss', + z; + + // Apparently there is -12:00 and +14:00 + // http://en.wikipedia.org/wiki/UTC+14:00 + // http://en.wikipedia.org/wiki/UTC-12:00 + for (z = -12; z <= 14; ++z) { + assert.equal(m.clone().zone(z * 60, true).format(fmt), m.format(fmt), + 'local to zone(' + z + ':00) failed to keep local time'); + } + }); + + test('local to zone, keepLocalTime = false', function (assert) { + var m = moment(), + z; + + // Apparently there is -12:00 and +14:00 + // http://en.wikipedia.org/wiki/UTC+14:00 + // http://en.wikipedia.org/wiki/UTC-12:00 + for (z = -12; z <= 14; ++z) { + assert.equal(m.clone().zone(z * 60).valueOf(), m.valueOf(), + 'local to zone(' + z + ':00) failed to keep utc time (implicit)'); + assert.equal(m.clone().zone(z * 60, false).valueOf(), m.valueOf(), + 'local to zone(' + z + ':00) failed to keep utc time (explicit)'); + } + }); + + test('utc to local, keepLocalTime = true', function (assert) { + var um = moment.utc(), + fmt = 'YYYY-DD-MM HH:mm:ss'; + + assert.equal(um.clone().local(true).format(fmt), um.format(fmt), 'utc to local failed to keep local time'); + }); + + test('utc to local, keepLocalTime = false', function (assert) { + var um = moment.utc(); + assert.equal(um.clone().local().valueOf(), um.valueOf(), 'utc to local failed to keep utc time (implicit)'); + assert.equal(um.clone().local(false).valueOf(), um.valueOf(), 'utc to local failed to keep utc time (explicit)'); + }); + + test('zone to local, keepLocalTime = true', function (assert) { + var m = moment(), + fmt = 'YYYY-DD-MM HH:mm:ss', + z; + + // Apparently there is -12:00 and +14:00 + // http://en.wikipedia.org/wiki/UTC+14:00 + // http://en.wikipedia.org/wiki/UTC-12:00 + for (z = -12; z <= 14; ++z) { + m.zone(z * 60); + + assert.equal(m.clone().local(true).format(fmt), m.format(fmt), + 'zone(' + z + ':00) to local failed to keep local time'); + } + }); + + test('zone to local, keepLocalTime = false', function (assert) { + var m = moment(), + z; + + // Apparently there is -12:00 and +14:00 + // http://en.wikipedia.org/wiki/UTC+14:00 + // http://en.wikipedia.org/wiki/UTC-12:00 + for (z = -12; z <= 14; ++z) { + m.zone(z * 60); + + assert.equal(m.clone().local(false).valueOf(), m.valueOf(), + 'zone(' + z + ':00) to local failed to keep utc time (explicit)'); + assert.equal(m.clone().local().valueOf(), m.valueOf(), + 'zone(' + z + ':00) to local failed to keep utc time (implicit)'); + } + }); + +})); + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; + + /*global QUnit:false*/ + + var test = QUnit.test; + + function module (name, lifecycle) { + QUnit.module(name, { + setup : function () { + moment.locale('en'); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + function localeModule (name, lifecycle) { + QUnit.module('locale:' + name, { + setup : function () { + moment.locale(name); + moment.createFromInputFallback = function () { + throw new Error('input not handled by moment'); + }; + if (lifecycle && lifecycle.setup) { + lifecycle.setup(); + } + }, + teardown : function () { + moment.locale('en'); + if (lifecycle && lifecycle.teardown) { + lifecycle.teardown(); + } + } + }); + } + + module('zones'); + + test('set zone', function (assert) { + var zone = moment(); + + zone.zone(0); + assert.equal(zone.zone(), 0, 'should be able to set the zone to 0'); + + zone.zone(60); + assert.equal(zone.zone(), 60, 'should be able to set the zone to 60'); + + zone.zone(-60); + assert.equal(zone.zone(), -60, 'should be able to set the zone to -60'); + }); + + test('set zone shorthand', function (assert) { + var zone = moment(); + + zone.zone(1); + assert.equal(zone.zone(), 60, 'setting the zone to 1 should imply hours and convert to 60'); + + zone.zone(-1); + assert.equal(zone.zone(), -60, 'setting the zone to -1 should imply hours and convert to -60'); + + zone.zone(15); + assert.equal(zone.zone(), 900, 'setting the zone to 15 should imply hours and convert to 900'); + + zone.zone(-15); + assert.equal(zone.zone(), -900, 'setting the zone to -15 should imply hours and convert to -900'); + + zone.zone(16); + assert.equal(zone.zone(), 16, 'setting the zone to 16 should imply minutes'); + + zone.zone(-16); + assert.equal(zone.zone(), -16, 'setting the zone to -16 should imply minutes'); + }); + + test('set zone with string', function (assert) { + var zone = moment(); + + zone.zone('+00:00'); + assert.equal(zone.zone(), 0, 'set the zone with a timezone string'); + + zone.zone('2013-03-07T07:00:00-08:00'); + assert.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'); + assert.equal(zone.zone(), -60, 'set the zone with a string that uses the +0000 syntax'); + + zone.zone('03-07-2013T07:00:00-08:00'); + assert.equal(zone.zone(), 480, 'set the zone with a string with a non-ISO 8601 date'); + }); + + test('change hours when changing the zone', function (assert) { + var zone = moment.utc([2000, 0, 1, 6]); + + zone.zone(0); + assert.equal(zone.hour(), 6, 'UTC 6AM should be 6AM at +0000'); + + zone.zone(60); + assert.equal(zone.hour(), 5, 'UTC 6AM should be 5AM at -0100'); + + zone.zone(-60); + assert.equal(zone.hour(), 7, 'UTC 6AM should be 7AM at +0100'); + }); + + test('change minutes when changing the zone', function (assert) { + var zone = moment.utc([2000, 0, 1, 6, 31]); + + zone.zone(0); + assert.equal(zone.format('HH:mm'), '06:31', 'UTC 6:31AM should be 6:31AM at +0000'); + + zone.zone(30); + assert.equal(zone.format('HH:mm'), '06:01', 'UTC 6:31AM should be 6:01AM at -0030'); + + zone.zone(-30); + assert.equal(zone.format('HH:mm'), '07:01', 'UTC 6:31AM should be 7:01AM at +0030'); + + zone.zone(1380); + assert.equal(zone.format('HH:mm'), '07:31', 'UTC 6:31AM should be 7:31AM at +1380'); + }); + + test('distance from the unix epoch', function (assert) { + var zoneA = moment(), + zoneB = moment(zoneA), + zoneC = moment(zoneA), + zoneD = moment(zoneA), + zoneE = moment(zoneA); + + zoneB.utc(); + assert.equal(+zoneA, +zoneB, 'moment should equal moment.utc'); + + zoneC.zone(-60); + assert.equal(+zoneA, +zoneC, 'moment should equal moment.zone(-60)'); + + zoneD.zone(480); + assert.equal(+zoneA, +zoneD, 'moment should equal moment.zone(480)'); + + zoneE.zone(1000); + assert.equal(+zoneA, +zoneE, 'moment should equal moment.zone(1000)'); + }); + + test('update offset after changing any values', function (assert) { + var oldOffset = moment.updateOffset, + m = moment.utc([2000, 6, 1]); + + moment.updateOffset = function (mom, keepTime) { + if (mom.__doChange) { + if (+mom > 962409600000) { + mom.zone(120, keepTime); + } else { + mom.zone(60, keepTime); + } + } + }; + + assert.equal(m.format('ZZ'), '+0000', 'should be at +0000'); + assert.equal(m.format('HH:mm'), '00:00', 'should start 12AM at +0000 timezone'); + + m.__doChange = true; + m.add(1, 'h'); + + assert.equal(m.format('ZZ'), '-0200', 'should be at -0200'); + assert.equal(m.format('HH:mm'), '23:00', '1AM at +0000 should be 11PM at -0200 timezone'); + + m.subtract(1, 'h'); + + assert.equal(m.format('ZZ'), '-0100', 'should be at -0100'); + assert.equal(m.format('HH:mm'), '23:00', '12AM at +0000 should be 11PM at -0100 timezone'); + + moment.updateOffset = oldOffset; + }); + + test('getters and setters', function (assert) { + var a = moment([2011, 5, 20]); + + assert.equal(a.clone().zone(120).year(2012).year(), 2012, 'should get and set year correctly'); + assert.equal(a.clone().zone(120).month(1).month(), 1, 'should get and set month correctly'); + assert.equal(a.clone().zone(120).date(2).date(), 2, 'should get and set date correctly'); + assert.equal(a.clone().zone(120).day(1).day(), 1, 'should get and set day correctly'); + assert.equal(a.clone().zone(120).hour(1).hour(), 1, 'should get and set hour correctly'); + assert.equal(a.clone().zone(120).minute(1).minute(), 1, 'should get and set minute correctly'); + }); + + test('getters', function (assert) { + var a = moment.utc([2012, 0, 1, 0, 0, 0]); + + assert.equal(a.clone().zone(120).year(), 2011, 'should get year correctly'); + assert.equal(a.clone().zone(120).month(), 11, 'should get month correctly'); + assert.equal(a.clone().zone(120).date(), 31, 'should get date correctly'); + assert.equal(a.clone().zone(120).hour(), 22, 'should get hour correctly'); + assert.equal(a.clone().zone(120).minute(), 0, 'should get minute correctly'); + + assert.equal(a.clone().zone(-120).year(), 2012, 'should get year correctly'); + assert.equal(a.clone().zone(-120).month(), 0, 'should get month correctly'); + assert.equal(a.clone().zone(-120).date(), 1, 'should get date correctly'); + assert.equal(a.clone().zone(-120).hour(), 2, 'should get hour correctly'); + assert.equal(a.clone().zone(-120).minute(), 0, 'should get minute correctly'); + + assert.equal(a.clone().zone(-90).year(), 2012, 'should get year correctly'); + assert.equal(a.clone().zone(-90).month(), 0, 'should get month correctly'); + assert.equal(a.clone().zone(-90).date(), 1, 'should get date correctly'); + assert.equal(a.clone().zone(-90).hour(), 1, 'should get hour correctly'); + assert.equal(a.clone().zone(-90).minute(), 30, 'should get minute correctly'); + }); + + test('from', function (assert) { + var zoneA = moment(), + zoneB = moment(zoneA).zone(720), + zoneC = moment(zoneA).zone(360), + zoneD = moment(zoneA).zone(-690), + other = moment(zoneA).add(35, 'm'); + + assert.equal(zoneA.from(other), zoneB.from(other), 'moment#from should be the same in all zones'); + assert.equal(zoneA.from(other), zoneC.from(other), 'moment#from should be the same in all zones'); + assert.equal(zoneA.from(other), zoneD.from(other), 'moment#from should be the same in all zones'); + }); + + test('diff', function (assert) { + var zoneA = moment(), + zoneB = moment(zoneA).zone(720), + zoneC = moment(zoneA).zone(360), + zoneD = moment(zoneA).zone(-690), + other = moment(zoneA).add(35, 'm'); + + assert.equal(zoneA.diff(other), zoneB.diff(other), 'moment#diff should be the same in all zones'); + assert.equal(zoneA.diff(other), zoneC.diff(other), 'moment#diff should be the same in all zones'); + assert.equal(zoneA.diff(other), zoneD.diff(other), 'moment#diff should be the same in all zones'); + + assert.equal(zoneA.diff(other, 'minute', true), zoneB.diff(other, 'minute', true), 'moment#diff should be the same in all zones'); + assert.equal(zoneA.diff(other, 'minute', true), zoneC.diff(other, 'minute', true), 'moment#diff should be the same in all zones'); + assert.equal(zoneA.diff(other, 'minute', true), zoneD.diff(other, 'minute', true), 'moment#diff should be the same in all zones'); + + assert.equal(zoneA.diff(other, 'hour', true), zoneB.diff(other, 'hour', true), 'moment#diff should be the same in all zones'); + assert.equal(zoneA.diff(other, 'hour', true), zoneC.diff(other, 'hour', true), 'moment#diff should be the same in all zones'); + assert.equal(zoneA.diff(other, 'hour', true), zoneD.diff(other, 'hour', true), 'moment#diff should be the same in all zones'); + }); + + test('unix offset and timestamp', function (assert) { + var zoneA = moment(), + zoneB = moment(zoneA).zone(720), + zoneC = moment(zoneA).zone(360), + zoneD = moment(zoneA).zone(-690); + + assert.equal(zoneA.unix(), zoneB.unix(), 'moment#unix should be the same in all zones'); + assert.equal(zoneA.unix(), zoneC.unix(), 'moment#unix should be the same in all zones'); + assert.equal(zoneA.unix(), zoneD.unix(), 'moment#unix should be the same in all zones'); + + assert.equal(+zoneA, +zoneB, 'moment#valueOf should be the same in all zones'); + assert.equal(+zoneA, +zoneC, 'moment#valueOf should be the same in all zones'); + assert.equal(+zoneA, +zoneD, 'moment#valueOf should be the same in all zones'); + }); + + test('cloning', function (assert) { + assert.equal(moment().zone(120).clone().zone(), 120, 'explicit cloning should retain the zone'); + assert.equal(moment().zone(-120).clone().zone(), -120, 'explicit cloning should retain the zone'); + assert.equal(moment(moment().zone(120)).zone(), 120, 'implicit cloning should retain the zone'); + assert.equal(moment(moment().zone(-120)).zone(), -120, 'implicit cloning should retain the zone'); + }); + + test('start of / end of', function (assert) { + var a = moment.utc([2010, 1, 2, 0, 0, 0]).zone(450); + + assert.equal(a.clone().startOf('day').hour(), 0, 'start of day should work on moments with a zone'); + assert.equal(a.clone().startOf('day').minute(), 0, 'start of day should work on moments with a zone'); + assert.equal(a.clone().startOf('hour').minute(), 0, 'start of hour should work on moments with a zone'); + + assert.equal(a.clone().endOf('day').hour(), 23, 'end of day should work on moments with a zone'); + assert.equal(a.clone().endOf('day').minute(), 59, 'end of day should work on moments with a zone'); + assert.equal(a.clone().endOf('hour').minute(), 59, 'end of hour should work on moments with a zone'); + }); + + test('reset zone with moment#utc', function (assert) { + var a = moment.utc([2012]).zone(480); + + assert.equal(a.clone().hour(), 16, 'different zone should have different hour'); + assert.equal(a.clone().utc().hour(), 0, 'calling moment#utc should reset the offset'); + }); + + test('reset zone with moment#local', function (assert) { + var a = moment([2012]).zone(480); + + assert.equal(a.clone().local().hour(), 0, 'calling moment#local should reset the offset'); + }); + + test('toDate', function (assert) { + var zoneA = new Date(), + zoneB = moment(zoneA).zone(720).toDate(), + zoneC = moment(zoneA).zone(360).toDate(), + zoneD = moment(zoneA).zone(-690).toDate(); + + assert.equal(+zoneA, +zoneB, 'moment#toDate should output a date with the right unix timestamp'); + assert.equal(+zoneA, +zoneC, 'moment#toDate should output a date with the right unix timestamp'); + assert.equal(+zoneA, +zoneD, 'moment#toDate should output a date with the right unix timestamp'); + }); + + test('same / before / after', function (assert) { + var zoneA = moment().utc(), + zoneB = moment(zoneA).zone(120), + zoneC = moment(zoneA).zone(-120); + + assert.ok(zoneA.isSame(zoneB), 'two moments with different offsets should be the same'); + assert.ok(zoneA.isSame(zoneC), 'two moments with different offsets should be the same'); + + assert.ok(zoneA.isSame(zoneB, 'hour'), 'two moments with different offsets should be the same hour'); + assert.ok(zoneA.isSame(zoneC, 'hour'), 'two moments with different offsets should be the same hour'); + + zoneA.add(1, 'hour'); + + assert.ok(zoneA.isAfter(zoneB), 'isAfter should work with two moments with different offsets'); + assert.ok(zoneA.isAfter(zoneC), 'isAfter should work with two moments with different offsets'); + + assert.ok(zoneA.isAfter(zoneB, 'hour'), 'isAfter:hour should work with two moments with different offsets'); + assert.ok(zoneA.isAfter(zoneC, 'hour'), 'isAfter:hour should work with two moments with different offsets'); + + zoneA.subtract(2, 'hour'); + + assert.ok(zoneA.isBefore(zoneB), 'isBefore should work with two moments with different offsets'); + assert.ok(zoneA.isBefore(zoneC), 'isBefore should work with two moments with different offsets'); + + assert.ok(zoneA.isBefore(zoneB, 'hour'), 'isBefore:hour should work with two moments with different offsets'); + assert.ok(zoneA.isBefore(zoneC, 'hour'), 'isBefore:hour should work with two moments with different offsets'); + }); + + test('add / subtract over dst', function (assert) { + var oldOffset = moment.updateOffset, + m = moment.utc([2000, 2, 31, 3]); + + moment.updateOffset = function (mom, keepTime) { + if (mom.clone().utc().month() > 2) { + mom.zone(-60, keepTime); + } else { + mom.zone(0, keepTime); + } + }; + + assert.equal(m.hour(), 3, 'should start at 00:00'); + + m.add(24, 'hour'); + + assert.equal(m.hour(), 4, 'adding 24 hours should disregard dst'); + + m.subtract(24, 'hour'); + + assert.equal(m.hour(), 3, 'subtracting 24 hours should disregard dst'); + + m.add(1, 'day'); + + assert.equal(m.hour(), 3, 'adding 1 day should have the same hour'); + + m.subtract(1, 'day'); + + assert.equal(m.hour(), 3, 'subtracting 1 day should have the same hour'); + + m.add(1, 'month'); + + assert.equal(m.hour(), 3, 'adding 1 month should have the same hour'); + + m.subtract(1, 'month'); + + assert.equal(m.hour(), 3, 'subtracting 1 month should have the same hour'); + + moment.updateOffset = oldOffset; + }); + + test('isDST', function (assert) { + var oldOffset = moment.updateOffset; + + moment.updateOffset = function (mom, keepTime) { + if (mom.month() > 2 && mom.month() < 9) { + mom.zone(-60, keepTime); + } else { + mom.zone(0, keepTime); + } + }; + + assert.ok(!moment().month(0).isDST(), 'Jan should not be summer dst'); + assert.ok(moment().month(6).isDST(), 'Jul should be summer dst'); + assert.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); + } + }; + + assert.ok(moment().month(0).isDST(), 'Jan should be winter dst'); + assert.ok(!moment().month(6).isDST(), 'Jul should not be winter dst'); + assert.ok(moment().month(11).isDST(), 'Dec should be winter dst'); + + moment.updateOffset = oldOffset; + }); + + test('zone names', function (assert) { + assert.equal(moment().zoneAbbr(), '', 'Local zone abbr should be empty'); + assert.equal(moment().format('z'), '', 'Local zone formatted abbr should be empty'); + assert.equal(moment().zoneName(), '', 'Local zone name should be empty'); + assert.equal(moment().format('zz'), '', 'Local zone formatted name should be empty'); + + assert.equal(moment.utc().zoneAbbr(), 'UTC', 'UTC zone abbr should be UTC'); + assert.equal(moment.utc().format('z'), 'UTC', 'UTC zone formatted abbr should be UTC'); + assert.equal(moment.utc().zoneName(), 'Coordinated Universal Time', 'UTC zone abbr should be Coordinated Universal Time'); + assert.equal(moment.utc().format('zz'), 'Coordinated Universal Time', 'UTC zone formatted abbr should be Coordinated Universal Time'); + }); + + test('hours alignment with UTC', function (assert) { + assert.equal(moment().zone(120).hasAlignedHourOffset(), true); + assert.equal(moment().zone(-180).hasAlignedHourOffset(), true); + assert.equal(moment().zone(90).hasAlignedHourOffset(), false); + assert.equal(moment().zone(-90).hasAlignedHourOffset(), false); + }); + + test('hours alignment with other zone', function (assert) { + var m = moment().zone(120); + + assert.equal(m.hasAlignedHourOffset(moment().zone(180)), true); + assert.equal(m.hasAlignedHourOffset(moment().zone(-180)), true); + assert.equal(m.hasAlignedHourOffset(moment().zone(90)), false); + assert.equal(m.hasAlignedHourOffset(moment().zone(-90)), false); + + m = moment().zone(90); + + assert.equal(m.hasAlignedHourOffset(moment().zone(180)), false); + assert.equal(m.hasAlignedHourOffset(moment().zone(-180)), false); + assert.equal(m.hasAlignedHourOffset(moment().zone(30)), true); + assert.equal(m.hasAlignedHourOffset(moment().zone(-30)), true); + + m = moment().zone(-60); + + assert.equal(m.hasAlignedHourOffset(moment().zone(180)), true); + assert.equal(m.hasAlignedHourOffset(moment().zone(-180)), true); + assert.equal(m.hasAlignedHourOffset(moment().zone(90)), false); + assert.equal(m.hasAlignedHourOffset(moment().zone(-90)), false); + + m = moment().zone(25); + + assert.equal(m.hasAlignedHourOffset(moment().zone(-35)), true); + assert.equal(m.hasAlignedHourOffset(moment().zone(85)), true); + + assert.equal(m.hasAlignedHourOffset(moment().zone(35)), false); + assert.equal(m.hasAlignedHourOffset(moment().zone(-85)), false); + }); + + test('parse zone', function (assert) { + var m = moment('2013-01-01T00:00:00-13:00').parseZone(); + assert.equal(m.zone(), 13 * 60); + assert.equal(m.hours(), 0); + }); + + test('parse zone static', function (assert) { + var m = moment.parseZone('2013-01-01T00:00:00-13:00'); + assert.equal(m.zone(), 13 * 60); + assert.equal(m.hours(), 0); + }); + + test('parse zone with more arguments', function (assert) { + var m; + m = moment.parseZone('2013 01 01 05 -13:00', 'YYYY MM DD HH ZZ'); + assert.equal(m.format(), '2013-01-01T05:00:00-13:00', 'accept input and format'); + m = moment.parseZone('2013-01-01-13:00', 'YYYY MM DD ZZ', true); + assert.equal(m.isValid(), false, 'accept input, format and strict flag'); + m = moment.parseZone('2013-01-01-13:00', ['DD MM YYYY ZZ', 'YYYY MM DD ZZ']); + assert.equal(m.format(), '2013-01-01T00:00:00-13:00', 'accept input and array of formats'); + }); + + test('parse zone with a timezone from the format string', function (assert) { + var m = moment('11-12-2013 -0400 +1100', 'DD-MM-YYYY ZZ #####').parseZone(); + + assert.equal(m.zone(), 4 * 60); + }); + + test('parse zone without a timezone included in the format string', function (assert) { + var m = moment('11-12-2013 -0400 +1100', 'DD-MM-YYYY').parseZone(); + + assert.equal(m.zone(), -11 * 60); + }); + + test('timezone format', function (assert) { + assert.equal(moment().zone(-60).format('ZZ'), '+0100', '-60 -> +0100'); + assert.equal(moment().zone(-90).format('ZZ'), '+0130', '-90 -> +0130'); + assert.equal(moment().zone(-120).format('ZZ'), '+0200', '-120 -> +0200'); + + assert.equal(moment().zone(+60).format('ZZ'), '-0100', '+60 -> -0100'); + assert.equal(moment().zone(+90).format('ZZ'), '-0130', '+90 -> -0130'); + assert.equal(moment().zone(+120).format('ZZ'), '-0200', '+120 -> -0200'); + }); + +}));
\ No newline at end of file diff --git a/bower_components/moment/moment.js b/bower_components/moment/moment.js new file mode 100644 index 0000000..275a3c3 --- /dev/null +++ b/bower_components/moment/moment.js @@ -0,0 +1,3111 @@ +//! moment.js +//! version : 2.10.3 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : + typeof define === 'function' && define.amd ? define(factory) : + global.moment = factory() +}(this, function () { 'use strict'; + + var hookCallback; + + function utils_hooks__hooks () { + return hookCallback.apply(null, arguments); + } + + // This is done to register the method called with moment() + // without creating circular dependencies. + function setHookCallback (callback) { + hookCallback = callback; + } + + function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; + } + + function isDate(input) { + return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]'; + } + + function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; + } + + function hasOwnProp(a, b) { + return Object.prototype.hasOwnProperty.call(a, b); + } + + function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } + } + + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } + + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; + } + + return a; + } + + function create_utc__createUTC (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, true).utc(); + } + + function defaultParsingFlags() { + // We need to deep clone this object. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso : false + }; + } + + function getParsingFlags(m) { + if (m._pf == null) { + m._pf = defaultParsingFlags(); + } + return m._pf; + } + + function valid__isValid(m) { + if (m._isValid == null) { + var flags = getParsingFlags(m); + m._isValid = !isNaN(m._d.getTime()) && + flags.overflow < 0 && + !flags.empty && + !flags.invalidMonth && + !flags.nullInput && + !flags.invalidFormat && + !flags.userInvalidated; + + if (m._strict) { + m._isValid = m._isValid && + flags.charsLeftOver === 0 && + flags.unusedTokens.length === 0 && + flags.bigHour === undefined; + } + } + return m._isValid; + } + + function valid__createInvalid (flags) { + var m = create_utc__createUTC(NaN); + if (flags != null) { + extend(getParsingFlags(m), flags); + } + else { + getParsingFlags(m).userInvalidated = true; + } + + return m; + } + + var momentProperties = utils_hooks__hooks.momentProperties = []; + + function copyConfig(to, from) { + var i, prop, val; + + if (typeof from._isAMomentObject !== 'undefined') { + to._isAMomentObject = from._isAMomentObject; + } + if (typeof from._i !== 'undefined') { + to._i = from._i; + } + if (typeof from._f !== 'undefined') { + to._f = from._f; + } + if (typeof from._l !== 'undefined') { + to._l = from._l; + } + if (typeof from._strict !== 'undefined') { + to._strict = from._strict; + } + if (typeof from._tzm !== 'undefined') { + to._tzm = from._tzm; + } + if (typeof from._isUTC !== 'undefined') { + to._isUTC = from._isUTC; + } + if (typeof from._offset !== 'undefined') { + to._offset = from._offset; + } + if (typeof from._pf !== 'undefined') { + to._pf = getParsingFlags(from); + } + if (typeof from._locale !== 'undefined') { + to._locale = from._locale; + } + + if (momentProperties.length > 0) { + for (i in momentProperties) { + prop = momentProperties[i]; + val = from[prop]; + if (typeof val !== 'undefined') { + to[prop] = val; + } + } + } + + return to; + } + + var updateInProgress = false; + + // Moment prototype object + function Moment(config) { + copyConfig(this, config); + this._d = new Date(+config._d); + // Prevent infinite loop in case updateOffset creates new moment + // objects. + if (updateInProgress === false) { + updateInProgress = true; + utils_hooks__hooks.updateOffset(this); + updateInProgress = false; + } + } + + function isMoment (obj) { + return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); + } + + function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; + + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + if (coercedNumber >= 0) { + value = Math.floor(coercedNumber); + } else { + value = Math.ceil(coercedNumber); + } + } + + return value; + } + + function compareArrays(array1, array2, dontConvert) { + 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 ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; + } + + function Locale() { + } + + var locales = {}; + var globalLocale; + + function normalizeLocale(key) { + return key ? key.toLowerCase().replace('_', '-') : key; + } + + // pick the locale from the array + // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each + // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root + function chooseLocale(names) { + var i = 0, j, next, locale, split; + + while (i < names.length) { + split = normalizeLocale(names[i]).split('-'); + j = split.length; + next = normalizeLocale(names[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + locale = loadLocale(split.slice(0, j).join('-')); + if (locale) { + return locale; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return null; + } + + function loadLocale(name) { + var oldLocale = null; + // TODO: Find a better way to register and load all the locales in Node + if (!locales[name] && typeof module !== 'undefined' && + module && module.exports) { + try { + oldLocale = globalLocale._abbr; + require('./locale/' + name); + // because defineLocale currently also sets the global locale, we + // want to undo that for lazy loaded locales + locale_locales__getSetGlobalLocale(oldLocale); + } catch (e) { } + } + return locales[name]; + } + + // This function will load locale and then set the global locale. If + // no arguments are passed in, it will simply return the current global + // locale key. + function locale_locales__getSetGlobalLocale (key, values) { + var data; + if (key) { + if (typeof values === 'undefined') { + data = locale_locales__getLocale(key); + } + else { + data = defineLocale(key, values); + } + + if (data) { + // moment.duration._locale = moment._locale = data; + globalLocale = data; + } + } + + return globalLocale._abbr; + } + + function defineLocale (name, values) { + if (values !== null) { + values.abbr = name; + if (!locales[name]) { + locales[name] = new Locale(); + } + locales[name].set(values); + + // backwards compat for now: also set the locale + locale_locales__getSetGlobalLocale(name); + + return locales[name]; + } else { + // useful for testing + delete locales[name]; + return null; + } + } + + // returns locale data + function locale_locales__getLocale (key) { + var locale; + + if (key && key._locale && key._locale._abbr) { + key = key._locale._abbr; + } + + if (!key) { + return globalLocale; + } + + if (!isArray(key)) { + //short-circuit everything else + locale = loadLocale(key); + if (locale) { + return locale; + } + key = [key]; + } + + return chooseLocale(key); + } + + var aliases = {}; + + function addUnitAlias (unit, shorthand) { + var lowerCase = unit.toLowerCase(); + aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit; + } + + function normalizeUnits(units) { + return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined; + } + + function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (hasOwnProp(inputObject, prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; + } + + function makeGetSet (unit, keepTime) { + return function (value) { + if (value != null) { + get_set__set(this, unit, value); + utils_hooks__hooks.updateOffset(this, keepTime); + return this; + } else { + return get_set__get(this, unit); + } + }; + } + + function get_set__get (mom, unit) { + return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); + } + + function get_set__set (mom, unit, value) { + return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); + } + + // MOMENTS + + function getSet (units, value) { + var unit; + if (typeof units === 'object') { + for (unit in units) { + this.set(unit, units[unit]); + } + } else { + units = normalizeUnits(units); + if (typeof this[units] === 'function') { + return this[units](value); + } + } + return this; + } + + function zeroFill(number, targetLength, forceSign) { + var output = '' + Math.abs(number), + sign = number >= 0; + + while (output.length < targetLength) { + output = '0' + output; + } + return (sign ? (forceSign ? '+' : '') : '-') + output; + } + + var formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g; + + var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; + + var formatFunctions = {}; + + var formatTokenFunctions = {}; + + // token: 'M' + // padded: ['MM', 2] + // ordinal: 'Mo' + // callback: function () { this.month() + 1 } + function addFormatToken (token, padded, ordinal, callback) { + var func = callback; + if (typeof callback === 'string') { + func = function () { + return this[callback](); + }; + } + if (token) { + formatTokenFunctions[token] = func; + } + if (padded) { + formatTokenFunctions[padded[0]] = function () { + return zeroFill(func.apply(this, arguments), padded[1], padded[2]); + }; + } + if (ordinal) { + formatTokenFunctions[ordinal] = function () { + return this.localeData().ordinal(func.apply(this, arguments), token); + }; + } + } + + function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + 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) { + if (!m.isValid()) { + return m.localeData().invalidDate(); + } + + format = expandFormat(format, m.localeData()); + + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } + + return formatFunctions[format](m); + } + + function expandFormat(format, locale) { + var i = 5; + + function replaceLongDateFormatTokens(input) { + return locale.longDateFormat(input) || input; + } + + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } + + return format; + } + + var match1 = /\d/; // 0 - 9 + var match2 = /\d\d/; // 00 - 99 + var match3 = /\d{3}/; // 000 - 999 + var match4 = /\d{4}/; // 0000 - 9999 + var match6 = /[+-]?\d{6}/; // -999999 - 999999 + var match1to2 = /\d\d?/; // 0 - 99 + var match1to3 = /\d{1,3}/; // 0 - 999 + var match1to4 = /\d{1,4}/; // 0 - 9999 + var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 + + var matchUnsigned = /\d+/; // 0 - inf + var matchSigned = /[+-]?\d+/; // -inf - inf + + var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z + + var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 + + // any word (or two) characters or numbers including two/three word month in arabic. + var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i; + + var regexes = {}; + + function addRegexToken (token, regex, strictRegex) { + regexes[token] = typeof regex === 'function' ? regex : function (isStrict) { + return (isStrict && strictRegex) ? strictRegex : regex; + }; + } + + function getParseRegexForToken (token, config) { + if (!hasOwnProp(regexes, token)) { + return new RegExp(unescapeFormat(token)); + } + + return regexes[token](config._strict, config._locale); + } + + // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript + function unescapeFormat(s) { + return s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + }).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); + } + + var tokens = {}; + + function addParseToken (token, callback) { + var i, func = callback; + if (typeof token === 'string') { + token = [token]; + } + if (typeof callback === 'number') { + func = function (input, array) { + array[callback] = toInt(input); + }; + } + for (i = 0; i < token.length; i++) { + tokens[token[i]] = func; + } + } + + function addWeekParseToken (token, callback) { + addParseToken(token, function (input, array, config, token) { + config._w = config._w || {}; + callback(input, config._w, config, token); + }); + } + + function addTimeToArrayFromToken(token, input, config) { + if (input != null && hasOwnProp(tokens, token)) { + tokens[token](input, config._a, config, token); + } + } + + var YEAR = 0; + var MONTH = 1; + var DATE = 2; + var HOUR = 3; + var MINUTE = 4; + var SECOND = 5; + var MILLISECOND = 6; + + function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); + } + + // FORMATTING + + addFormatToken('M', ['MM', 2], 'Mo', function () { + return this.month() + 1; + }); + + addFormatToken('MMM', 0, 0, function (format) { + return this.localeData().monthsShort(this, format); + }); + + addFormatToken('MMMM', 0, 0, function (format) { + return this.localeData().months(this, format); + }); + + // ALIASES + + addUnitAlias('month', 'M'); + + // PARSING + + addRegexToken('M', match1to2); + addRegexToken('MM', match1to2, match2); + addRegexToken('MMM', matchWord); + addRegexToken('MMMM', matchWord); + + addParseToken(['M', 'MM'], function (input, array) { + array[MONTH] = toInt(input) - 1; + }); + + addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { + var month = config._locale.monthsParse(input, token, config._strict); + // if we didn't find a month name, mark the date as invalid. + if (month != null) { + array[MONTH] = month; + } else { + getParsingFlags(config).invalidMonth = input; + } + }); + + // LOCALES + + var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'); + function localeMonths (m) { + return this._months[m.month()]; + } + + var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'); + function localeMonthsShort (m) { + return this._monthsShort[m.month()]; + } + + function localeMonthsParse (monthName, format, strict) { + var i, mom, regex; + + if (!this._monthsParse) { + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + } + + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = create_utc__createUTC([2000, i]); + if (strict && !this._longMonthsParse[i]) { + this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); + this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); + } + if (!strict && !this._monthsParse[i]) { + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { + return i; + } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { + return i; + } else if (!strict && this._monthsParse[i].test(monthName)) { + return i; + } + } + } + + // MOMENTS + + function setMonth (mom, value) { + var dayOfMonth; + + // TODO: Move this out of here! + if (typeof value === 'string') { + value = mom.localeData().monthsParse(value); + // TODO: Another silent failure? + if (typeof value !== 'number') { + return mom; + } + } + + dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; + } + + function getSetMonth (value) { + if (value != null) { + setMonth(this, value); + utils_hooks__hooks.updateOffset(this, true); + return this; + } else { + return get_set__get(this, 'Month'); + } + } + + function getDaysInMonth () { + return daysInMonth(this.year(), this.month()); + } + + function checkOverflow (m) { + var overflow; + var a = m._a; + + if (a && getParsingFlags(m).overflow === -2) { + overflow = + a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : + a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : + a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR : + a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : + a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : + a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : + -1; + + if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } + + getParsingFlags(m).overflow = overflow; + } + + return m; + } + + function warn(msg) { + if (utils_hooks__hooks.suppressDeprecationWarnings === false && typeof console !== 'undefined' && console.warn) { + console.warn('Deprecation warning: ' + msg); + } + } + + function deprecate(msg, fn) { + var firstTime = true, + msgWithStack = msg + '\n' + (new Error()).stack; + + return extend(function () { + if (firstTime) { + warn(msgWithStack); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); + } + + var deprecations = {}; + + function deprecateSimple(name, msg) { + if (!deprecations[name]) { + warn(msg); + deprecations[name] = true; + } + } + + utils_hooks__hooks.suppressDeprecationWarnings = false; + + var from_string__isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/; + + var isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/], + ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/], + ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/], + ['GGGG-[W]WW', /\d{4}-W\d{2}/], + ['YYYY-DDD', /\d{4}-\d{3}/] + ]; + + // iso time formats and regexes + var isoTimes = [ + ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/], + ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], + ['HH:mm', /(T| )\d\d:\d\d/], + ['HH', /(T| )\d\d/] + ]; + + var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; + + // date from iso format + function configFromISO(config) { + var i, l, + string = config._i, + match = from_string__isoRegex.exec(string); + + if (match) { + getParsingFlags(config).iso = true; + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(string)) { + // match[5] should be 'T' or undefined + config._f = isoDates[i][0] + (match[6] || ' '); + break; + } + } + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(string)) { + config._f += isoTimes[i][0]; + break; + } + } + if (string.match(matchOffset)) { + config._f += 'Z'; + } + configFromStringAndFormat(config); + } else { + config._isValid = false; + } + } + + // date from iso format or fallback + function configFromString(config) { + var matched = aspNetJsonRegex.exec(config._i); + + if (matched !== null) { + config._d = new Date(+matched[1]); + return; + } + + configFromISO(config); + if (config._isValid === false) { + delete config._isValid; + utils_hooks__hooks.createFromInputFallback(config); + } + } + + utils_hooks__hooks.createFromInputFallback = deprecate( + 'moment construction falls back to js Date. This is ' + + 'discouraged and will be removed in upcoming major ' + + 'release. Please refer to ' + + 'https://github.com/moment/moment/issues/1407 for more info.', + function (config) { + config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); + } + ); + + function createDate (y, m, d, h, M, s, ms) { + //can't just apply() to create a date: + //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply + var date = new Date(y, m, d, h, M, s, ms); + + //the date constructor doesn't accept years < 1970 + if (y < 1970) { + date.setFullYear(y); + } + return date; + } + + function createUTCDate (y) { + var date = new Date(Date.UTC.apply(null, arguments)); + if (y < 1970) { + date.setUTCFullYear(y); + } + return date; + } + + addFormatToken(0, ['YY', 2], 0, function () { + return this.year() % 100; + }); + + addFormatToken(0, ['YYYY', 4], 0, 'year'); + addFormatToken(0, ['YYYYY', 5], 0, 'year'); + addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); + + // ALIASES + + addUnitAlias('year', 'y'); + + // PARSING + + addRegexToken('Y', matchSigned); + addRegexToken('YY', match1to2, match2); + addRegexToken('YYYY', match1to4, match4); + addRegexToken('YYYYY', match1to6, match6); + addRegexToken('YYYYYY', match1to6, match6); + + addParseToken(['YYYY', 'YYYYY', 'YYYYYY'], YEAR); + addParseToken('YY', function (input, array) { + array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input); + }); + + // HELPERS + + function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; + } + + function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; + } + + // HOOKS + + utils_hooks__hooks.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); + }; + + // MOMENTS + + var getSetYear = makeGetSet('FullYear', false); + + function getIsLeapYear () { + return isLeapYear(this.year()); + } + + addFormatToken('w', ['ww', 2], 'wo', 'week'); + addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); + + // ALIASES + + addUnitAlias('week', 'w'); + addUnitAlias('isoWeek', 'W'); + + // PARSING + + addRegexToken('w', match1to2); + addRegexToken('ww', match1to2, match2); + addRegexToken('W', match1to2); + addRegexToken('WW', match1to2, match2); + + addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { + week[token.substr(0, 1)] = toInt(input); + }); + + // HELPERS + + // 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 = local__createLocal(mom).add(daysToDayOfWeek, 'd'); + return { + week: Math.ceil(adjustedMoment.dayOfYear() / 7), + year: adjustedMoment.year() + }; + } + + // LOCALES + + function localeWeek (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; + } + + var defaultLocaleWeek = { + 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 localeFirstDayOfWeek () { + return this._week.dow; + } + + function localeFirstDayOfYear () { + return this._week.doy; + } + + // MOMENTS + + function getSetWeek (input) { + var week = this.localeData().week(this); + return input == null ? week : this.add((input - week) * 7, 'd'); + } + + function getSetISOWeek (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add((input - week) * 7, 'd'); + } + + addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); + + // ALIASES + + addUnitAlias('dayOfYear', 'DDD'); + + // PARSING + + addRegexToken('DDD', match1to3); + addRegexToken('DDDD', match3); + addParseToken(['DDD', 'DDDD'], function (input, array, config) { + config._dayOfYear = toInt(input); + }); + + // HELPERS + + //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday + function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { + var d = createUTCDate(year, 0, 1).getUTCDay(); + var daysToAdd; + var dayOfYear; + + d = d === 0 ? 7 : d; + weekday = weekday != null ? weekday : firstDayOfWeek; + daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); + dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; + + return { + year : dayOfYear > 0 ? year : year - 1, + dayOfYear : dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear + }; + } + + // MOMENTS + + function getSetDayOfYear (input) { + var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); + } + + // Pick the first defined of two or three arguments. + function defaults(a, b, c) { + if (a != null) { + return a; + } + if (b != null) { + return b; + } + return c; + } + + function currentDateArray(config) { + var now = new Date(); + if (config._useUTC) { + return [now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()]; + } + return [now.getFullYear(), now.getMonth(), now.getDate()]; + } + + // 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 configFromArray (config) { + var i, date, input = [], currentDate, yearToUse; + + if (config._d) { + return; + } + + currentDate = currentDateArray(config); + + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); + } + + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = defaults(config._a[YEAR], currentDate[YEAR]); + + if (config._dayOfYear > daysInYear(yearToUse)) { + getParsingFlags(config)._overflowDayOfYear = true; + } + + date = createUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } + + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } + + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } + + // Check for 24:00:00.000 + if (config._a[HOUR] === 24 && + config._a[MINUTE] === 0 && + config._a[SECOND] === 0 && + config._a[MILLISECOND] === 0) { + config._nextDay = true; + config._a[HOUR] = 0; + } + + config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input); + // Apply timezone offset from input. The actual utcOffset can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); + } + + if (config._nextDay) { + config._a[HOUR] = 24; + } + } + + function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp; + + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; + + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year); + week = defaults(w.W, 1); + weekday = defaults(w.E, 1); + } else { + dow = config._locale._week.dow; + doy = config._locale._week.doy; + + weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year); + week = defaults(w.w, 1); + + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < dow) { + ++week; + } + } else if (w.e != null) { + // local weekday -- counting starts from begining of week + weekday = w.e + dow; + } else { + // default to begining of week + weekday = dow; + } + } + temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow); + + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; + } + + utils_hooks__hooks.ISO_8601 = function () {}; + + // date from string and format string + function configFromStringAndFormat(config) { + // TODO: Move this to another part of the creation flow to prevent circular deps + if (config._f === utils_hooks__hooks.ISO_8601) { + configFromISO(config); + return; + } + + config._a = []; + getParsingFlags(config).empty = true; + + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; + + tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; + + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + getParsingFlags(config).unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + getParsingFlags(config).empty = false; + } + else { + getParsingFlags(config).unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + getParsingFlags(config).unusedTokens.push(token); + } + } + + // add remaining unparsed input length to the string + getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + getParsingFlags(config).unusedInput.push(string); + } + + // clear _12h flag if hour is <= 12 + if (getParsingFlags(config).bigHour === true && + config._a[HOUR] <= 12 && + config._a[HOUR] > 0) { + getParsingFlags(config).bigHour = undefined; + } + // handle meridiem + config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); + + configFromArray(config); + checkOverflow(config); + } + + + function meridiemFixWrap (locale, hour, meridiem) { + var isPm; + + if (meridiem == null) { + // nothing to do + return hour; + } + if (locale.meridiemHour != null) { + return locale.meridiemHour(hour, meridiem); + } else if (locale.isPM != null) { + // Fallback + isPm = locale.isPM(meridiem); + if (isPm && hour < 12) { + hour += 12; + } + if (!isPm && hour === 12) { + hour = 0; + } + return hour; + } else { + // this is not supposed to happen + return hour; + } + } + + function configFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + getParsingFlags(config).invalidFormat = true; + config._d = new Date(NaN); + return; + } + + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = copyConfig({}, config); + if (config._useUTC != null) { + tempConfig._useUTC = config._useUTC; + } + tempConfig._f = config._f[i]; + configFromStringAndFormat(tempConfig); + + if (!valid__isValid(tempConfig)) { + continue; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += getParsingFlags(tempConfig).charsLeftOver; + + //or tokens + currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; + + getParsingFlags(tempConfig).score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } + + extend(config, bestMoment || tempConfig); + } + + function configFromObject(config) { + if (config._d) { + return; + } + + var i = normalizeObjectUnits(config._i); + config._a = [i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond]; + + configFromArray(config); + } + + function createFromConfig (config) { + var input = config._i, + format = config._f, + res; + + config._locale = config._locale || locale_locales__getLocale(config._l); + + if (input === null || (format === undefined && input === '')) { + return valid__createInvalid({nullInput: true}); + } + + if (typeof input === 'string') { + config._i = input = config._locale.preparse(input); + } + + if (isMoment(input)) { + return new Moment(checkOverflow(input)); + } else if (isArray(format)) { + configFromStringAndArray(config); + } else if (format) { + configFromStringAndFormat(config); + } else if (isDate(input)) { + config._d = input; + } else { + configFromInput(config); + } + + res = new Moment(checkOverflow(config)); + if (res._nextDay) { + // Adding is smart enough around DST + res.add(1, 'd'); + res._nextDay = undefined; + } + + return res; + } + + function configFromInput(config) { + var input = config._i; + if (input === undefined) { + config._d = new Date(); + } else if (isDate(input)) { + config._d = new Date(+input); + } else if (typeof input === 'string') { + configFromString(config); + } else if (isArray(input)) { + config._a = map(input.slice(0), function (obj) { + return parseInt(obj, 10); + }); + configFromArray(config); + } else if (typeof(input) === 'object') { + configFromObject(config); + } else if (typeof(input) === 'number') { + // from milliseconds + config._d = new Date(input); + } else { + utils_hooks__hooks.createFromInputFallback(config); + } + } + + function createLocalOrUTC (input, format, locale, strict, isUTC) { + var c = {}; + + if (typeof(locale) === 'boolean') { + strict = locale; + locale = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c._isAMomentObject = true; + c._useUTC = c._isUTC = isUTC; + c._l = locale; + c._i = input; + c._f = format; + c._strict = strict; + + return createFromConfig(c); + } + + function local__createLocal (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, false); + } + + var prototypeMin = deprecate( + 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548', + function () { + var other = local__createLocal.apply(null, arguments); + return other < this ? this : other; + } + ); + + var prototypeMax = deprecate( + 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548', + function () { + var other = local__createLocal.apply(null, arguments); + return other > this ? this : other; + } + ); + + // Pick a moment m from moments so that m[fn](other) is true for all + // other. This relies on the function fn to be transitive. + // + // moments should either be an array of moment objects or an array, whose + // first element is an array of moment objects. + function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return local__createLocal(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (moments[i][fn](res)) { + res = moments[i]; + } + } + return res; + } + + // TODO: Use [].sort instead? + function min () { + var args = [].slice.call(arguments, 0); + + return pickBy('isBefore', args); + } + + function max () { + var args = [].slice.call(arguments, 0); + + return pickBy('isAfter', args); + } + + function Duration (duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + quarters = normalizedInput.quarter || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 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 + + quarters * 3 + + years * 12; + + this._data = {}; + + this._locale = locale_locales__getLocale(); + + this._bubble(); + } + + function isDuration (obj) { + return obj instanceof Duration; + } + + function offset (token, separator) { + addFormatToken(token, 0, 0, function () { + var offset = this.utcOffset(); + var sign = '+'; + if (offset < 0) { + offset = -offset; + sign = '-'; + } + return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2); + }); + } + + offset('Z', ':'); + offset('ZZ', ''); + + // PARSING + + addRegexToken('Z', matchOffset); + addRegexToken('ZZ', matchOffset); + addParseToken(['Z', 'ZZ'], function (input, array, config) { + config._useUTC = true; + config._tzm = offsetFromString(input); + }); + + // HELPERS + + // timezone chunker + // '+10:00' > ['10', '00'] + // '-1530' > ['-15', '30'] + var chunkOffset = /([\+\-]|\d\d)/gi; + + function offsetFromString(string) { + var matches = ((string || '').match(matchOffset) || []); + var chunk = matches[matches.length - 1] || []; + var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0]; + var minutes = +(parts[1] * 60) + toInt(parts[2]); + + return parts[0] === '+' ? minutes : -minutes; + } + + // Return a moment from input, that is local/utc/zone equivalent to model. + function cloneWithOffset(input, model) { + var res, diff; + if (model._isUTC) { + res = model.clone(); + diff = (isMoment(input) || isDate(input) ? +input : +local__createLocal(input)) - (+res); + // Use low-level api, because this fn is low-level api. + res._d.setTime(+res._d + diff); + utils_hooks__hooks.updateOffset(res, false); + return res; + } else { + return local__createLocal(input).local(); + } + return model._isUTC ? local__createLocal(input).zone(model._offset || 0) : local__createLocal(input).local(); + } + + function getDateOffset (m) { + // On Firefox.24 Date#getTimezoneOffset returns a floating point. + // https://github.com/moment/moment/pull/1871 + return -Math.round(m._d.getTimezoneOffset() / 15) * 15; + } + + // HOOKS + + // This function will be called whenever a moment is mutated. + // It is intended to keep the offset in sync with the timezone. + utils_hooks__hooks.updateOffset = function () {}; + + // MOMENTS + + // keepLocalTime = true means only change the timezone, without + // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> + // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset + // +0200, so we adjust the time as needed, to be valid. + // + // Keeping the time actually adds/subtracts (one hour) + // from the actual represented time. That is why we call updateOffset + // a second time. In case it wants us to change the offset again + // _changeInProgress == true case, then we have to adjust, because + // there is no such time in the given timezone. + function getSetOffset (input, keepLocalTime) { + var offset = this._offset || 0, + localAdjust; + if (input != null) { + if (typeof input === 'string') { + input = offsetFromString(input); + } + if (Math.abs(input) < 16) { + input = input * 60; + } + if (!this._isUTC && keepLocalTime) { + localAdjust = getDateOffset(this); + } + this._offset = input; + this._isUTC = true; + if (localAdjust != null) { + this.add(localAdjust, 'm'); + } + if (offset !== input) { + if (!keepLocalTime || this._changeInProgress) { + add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + utils_hooks__hooks.updateOffset(this, true); + this._changeInProgress = null; + } + } + return this; + } else { + return this._isUTC ? offset : getDateOffset(this); + } + } + + function getSetZone (input, keepLocalTime) { + if (input != null) { + if (typeof input !== 'string') { + input = -input; + } + + this.utcOffset(input, keepLocalTime); + + return this; + } else { + return -this.utcOffset(); + } + } + + function setOffsetToUTC (keepLocalTime) { + return this.utcOffset(0, keepLocalTime); + } + + function setOffsetToLocal (keepLocalTime) { + if (this._isUTC) { + this.utcOffset(0, keepLocalTime); + this._isUTC = false; + + if (keepLocalTime) { + this.subtract(getDateOffset(this), 'm'); + } + } + return this; + } + + function setOffsetToParsedOffset () { + if (this._tzm) { + this.utcOffset(this._tzm); + } else if (typeof this._i === 'string') { + this.utcOffset(offsetFromString(this._i)); + } + return this; + } + + function hasAlignedHourOffset (input) { + if (!input) { + input = 0; + } + else { + input = local__createLocal(input).utcOffset(); + } + + return (this.utcOffset() - input) % 60 === 0; + } + + function isDaylightSavingTime () { + return ( + this.utcOffset() > this.clone().month(0).utcOffset() || + this.utcOffset() > this.clone().month(5).utcOffset() + ); + } + + function isDaylightSavingTimeShifted () { + if (this._a) { + var other = this._isUTC ? create_utc__createUTC(this._a) : local__createLocal(this._a); + return this.isValid() && compareArrays(this._a, other.toArray()) > 0; + } + + return false; + } + + function isLocal () { + return !this._isUTC; + } + + function isUtcOffset () { + return this._isUTC; + } + + function isUtc () { + return this._isUTC && this._offset === 0; + } + + var aspNetRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/; + + // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html + // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere + var create__isoRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/; + + function create__createDuration (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + diffRes; + + if (isDuration(input)) { + duration = { + ms : input._milliseconds, + d : input._days, + M : input._months + }; + } else if (typeof input === 'number') { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : 0, + d : toInt(match[DATE]) * sign, + h : toInt(match[HOUR]) * sign, + m : toInt(match[MINUTE]) * sign, + s : toInt(match[SECOND]) * sign, + ms : toInt(match[MILLISECOND]) * sign + }; + } else if (!!(match = create__isoRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : parseIso(match[2], sign), + M : parseIso(match[3], sign), + d : parseIso(match[4], sign), + h : parseIso(match[5], sign), + m : parseIso(match[6], sign), + s : parseIso(match[7], sign), + w : parseIso(match[8], sign) + }; + } else if (duration == null) {// checks for null or undefined + duration = {}; + } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) { + diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to)); + + duration = {}; + duration.ms = diffRes.milliseconds; + duration.M = diffRes.months; + } + + ret = new Duration(duration); + + if (isDuration(input) && hasOwnProp(input, '_locale')) { + ret._locale = input._locale; + } + + return ret; + } + + create__createDuration.fn = Duration.prototype; + + function parseIso (inp, sign) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; + } + + function positiveMomentsDifference(base, other) { + var res = {milliseconds: 0, months: 0}; + + res.months = other.month() - base.month() + + (other.year() - base.year()) * 12; + if (base.clone().add(res.months, 'M').isAfter(other)) { + --res.months; + } + + res.milliseconds = +other - +(base.clone().add(res.months, 'M')); + + return res; + } + + function momentsDifference(base, other) { + var res; + other = cloneWithOffset(other, base); + if (base.isBefore(other)) { + res = positiveMomentsDifference(base, other); + } else { + res = positiveMomentsDifference(other, base); + res.milliseconds = -res.milliseconds; + res.months = -res.months; + } + + return res; + } + + function createAdder(direction, name) { + return function (val, period) { + var dur, tmp; + //invert the arguments, but complain about it + if (period !== null && !isNaN(+period)) { + deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).'); + tmp = val; val = period; period = tmp; + } + + val = typeof val === 'string' ? +val : val; + dur = create__createDuration(val, period); + add_subtract__addSubtract(this, dur, direction); + return this; + }; + } + + function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = duration._days, + months = duration._months; + updateOffset = updateOffset == null ? true : updateOffset; + + if (milliseconds) { + mom._d.setTime(+mom._d + milliseconds * isAdding); + } + if (days) { + get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding); + } + if (months) { + setMonth(mom, get_set__get(mom, 'Month') + months * isAdding); + } + if (updateOffset) { + utils_hooks__hooks.updateOffset(mom, days || months); + } + } + + var add_subtract__add = createAdder(1, 'add'); + var add_subtract__subtract = createAdder(-1, 'subtract'); + + function moment_calendar__calendar (time) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're local/utc/offset or not. + var now = time || local__createLocal(), + sod = cloneWithOffset(now, this).startOf('day'), + diff = this.diff(sod, '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.localeData().calendar(format, this, local__createLocal(now))); + } + + function clone () { + return new Moment(this); + } + + function isAfter (input, units) { + var inputMs; + units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); + if (units === 'millisecond') { + input = isMoment(input) ? input : local__createLocal(input); + return +this > +input; + } else { + inputMs = isMoment(input) ? +input : +local__createLocal(input); + return inputMs < +this.clone().startOf(units); + } + } + + function isBefore (input, units) { + var inputMs; + units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); + if (units === 'millisecond') { + input = isMoment(input) ? input : local__createLocal(input); + return +this < +input; + } else { + inputMs = isMoment(input) ? +input : +local__createLocal(input); + return +this.clone().endOf(units) < inputMs; + } + } + + function isBetween (from, to, units) { + return this.isAfter(from, units) && this.isBefore(to, units); + } + + function isSame (input, units) { + var inputMs; + units = normalizeUnits(units || 'millisecond'); + if (units === 'millisecond') { + input = isMoment(input) ? input : local__createLocal(input); + return +this === +input; + } else { + inputMs = +local__createLocal(input); + return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units)); + } + } + + function absFloor (number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); + } + } + + function diff (input, units, asFloat) { + var that = cloneWithOffset(input, this), + zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4, + delta, output; + + units = normalizeUnits(units); + + if (units === 'year' || units === 'month' || units === 'quarter') { + output = monthDiff(this, that); + if (units === 'quarter') { + output = output / 3; + } else if (units === 'year') { + output = output / 12; + } + } else { + delta = this - that; + output = units === 'second' ? delta / 1e3 : // 1000 + units === 'minute' ? delta / 6e4 : // 1000 * 60 + units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + delta; + } + return asFloat ? output : absFloor(output); + } + + function monthDiff (a, b) { + // difference in months + var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), + // b is in (anchor - 1 month, anchor + 1 month) + anchor = a.clone().add(wholeMonthDiff, 'months'), + anchor2, adjust; + + if (b - anchor < 0) { + anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor - anchor2); + } else { + anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor2 - anchor); + } + + return -(wholeMonthDiff + adjust); + } + + utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; + + function toString () { + return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); + } + + function moment_format__toISOString () { + var m = this.clone().utc(); + if (0 < m.year() && m.year() <= 9999) { + if ('function' === typeof Date.prototype.toISOString) { + // native implementation is ~50x faster, use it when we can + return this.toDate().toISOString(); + } else { + return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + } else { + return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + } + + function format (inputString) { + var output = formatMoment(this, inputString || utils_hooks__hooks.defaultFormat); + return this.localeData().postformat(output); + } + + function from (time, withoutSuffix) { + if (!this.isValid()) { + return this.localeData().invalidDate(); + } + return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); + } + + function fromNow (withoutSuffix) { + return this.from(local__createLocal(), withoutSuffix); + } + + function to (time, withoutSuffix) { + if (!this.isValid()) { + return this.localeData().invalidDate(); + } + return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix); + } + + function toNow (withoutSuffix) { + return this.to(local__createLocal(), withoutSuffix); + } + + function locale (key) { + var newLocaleData; + + if (key === undefined) { + return this._locale._abbr; + } else { + newLocaleData = locale_locales__getLocale(key); + if (newLocaleData != null) { + this._locale = newLocaleData; + } + return this; + } + } + + var lang = deprecate( + 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', + function (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); + } + } + ); + + function localeData () { + return this._locale; + } + + function startOf (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 'quarter': + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoWeek': + 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); + } + + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } + if (units === 'isoWeek') { + this.isoWeekday(1); + } + + // quarters are also special + if (units === 'quarter') { + this.month(Math.floor(this.month() / 3) * 3); + } + + return this; + } + + function endOf (units) { + units = normalizeUnits(units); + if (units === undefined || units === 'millisecond') { + return this; + } + return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); + } + + function to_type__valueOf () { + return +this._d - ((this._offset || 0) * 60000); + } + + function unix () { + return Math.floor(+this / 1000); + } + + function toDate () { + return this._offset ? new Date(+this) : this._d; + } + + function toArray () { + var m = this; + return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()]; + } + + function moment_valid__isValid () { + return valid__isValid(this); + } + + function parsingFlags () { + return extend({}, getParsingFlags(this)); + } + + function invalidAt () { + return getParsingFlags(this).overflow; + } + + addFormatToken(0, ['gg', 2], 0, function () { + return this.weekYear() % 100; + }); + + addFormatToken(0, ['GG', 2], 0, function () { + return this.isoWeekYear() % 100; + }); + + function addWeekYearFormatToken (token, getter) { + addFormatToken(0, [token, token.length], 0, getter); + } + + addWeekYearFormatToken('gggg', 'weekYear'); + addWeekYearFormatToken('ggggg', 'weekYear'); + addWeekYearFormatToken('GGGG', 'isoWeekYear'); + addWeekYearFormatToken('GGGGG', 'isoWeekYear'); + + // ALIASES + + addUnitAlias('weekYear', 'gg'); + addUnitAlias('isoWeekYear', 'GG'); + + // PARSING + + addRegexToken('G', matchSigned); + addRegexToken('g', matchSigned); + addRegexToken('GG', match1to2, match2); + addRegexToken('gg', match1to2, match2); + addRegexToken('GGGG', match1to4, match4); + addRegexToken('gggg', match1to4, match4); + addRegexToken('GGGGG', match1to6, match6); + addRegexToken('ggggg', match1to6, match6); + + addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) { + week[token.substr(0, 2)] = toInt(input); + }); + + addWeekParseToken(['gg', 'GG'], function (input, week, config, token) { + week[token] = utils_hooks__hooks.parseTwoDigitYear(input); + }); + + // HELPERS + + function weeksInYear(year, dow, doy) { + return weekOfYear(local__createLocal([year, 11, 31 + dow - doy]), dow, doy).week; + } + + // MOMENTS + + function getSetWeekYear (input) { + var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year; + return input == null ? year : this.add((input - year), 'y'); + } + + function getSetISOWeekYear (input) { + var year = weekOfYear(this, 1, 4).year; + return input == null ? year : this.add((input - year), 'y'); + } + + function getISOWeeksInYear () { + return weeksInYear(this.year(), 1, 4); + } + + function getWeeksInYear () { + var weekInfo = this.localeData()._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); + } + + addFormatToken('Q', 0, 0, 'quarter'); + + // ALIASES + + addUnitAlias('quarter', 'Q'); + + // PARSING + + addRegexToken('Q', match1); + addParseToken('Q', function (input, array) { + array[MONTH] = (toInt(input) - 1) * 3; + }); + + // MOMENTS + + function getSetQuarter (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); + } + + addFormatToken('D', ['DD', 2], 'Do', 'date'); + + // ALIASES + + addUnitAlias('date', 'D'); + + // PARSING + + addRegexToken('D', match1to2); + addRegexToken('DD', match1to2, match2); + addRegexToken('Do', function (isStrict, locale) { + return isStrict ? locale._ordinalParse : locale._ordinalParseLenient; + }); + + addParseToken(['D', 'DD'], DATE); + addParseToken('Do', function (input, array) { + array[DATE] = toInt(input.match(match1to2)[0], 10); + }); + + // MOMENTS + + var getSetDayOfMonth = makeGetSet('Date', true); + + addFormatToken('d', 0, 'do', 'day'); + + addFormatToken('dd', 0, 0, function (format) { + return this.localeData().weekdaysMin(this, format); + }); + + addFormatToken('ddd', 0, 0, function (format) { + return this.localeData().weekdaysShort(this, format); + }); + + addFormatToken('dddd', 0, 0, function (format) { + return this.localeData().weekdays(this, format); + }); + + addFormatToken('e', 0, 0, 'weekday'); + addFormatToken('E', 0, 0, 'isoWeekday'); + + // ALIASES + + addUnitAlias('day', 'd'); + addUnitAlias('weekday', 'e'); + addUnitAlias('isoWeekday', 'E'); + + // PARSING + + addRegexToken('d', match1to2); + addRegexToken('e', match1to2); + addRegexToken('E', match1to2); + addRegexToken('dd', matchWord); + addRegexToken('ddd', matchWord); + addRegexToken('dddd', matchWord); + + addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config) { + var weekday = config._locale.weekdaysParse(input); + // if we didn't get a weekday name, mark the date as invalid + if (weekday != null) { + week.d = weekday; + } else { + getParsingFlags(config).invalidWeekday = input; + } + }); + + addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { + week[token] = toInt(input); + }); + + // HELPERS + + function parseWeekday(input, locale) { + if (typeof input === 'string') { + if (!isNaN(input)) { + input = parseInt(input, 10); + } + else { + input = locale.weekdaysParse(input); + if (typeof input !== 'number') { + return null; + } + } + } + return input; + } + + // LOCALES + + var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'); + function localeWeekdays (m) { + return this._weekdays[m.day()]; + } + + var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'); + function localeWeekdaysShort (m) { + return this._weekdaysShort[m.day()]; + } + + var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'); + function localeWeekdaysMin (m) { + return this._weekdaysMin[m.day()]; + } + + function localeWeekdaysParse (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 = local__createLocal([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; + } + } + } + + // MOMENTS + + function getSetDayOfWeek (input) { + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.localeData()); + return this.add(input - day, 'd'); + } else { + return day; + } + } + + function getSetLocaleDayOfWeek (input) { + var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; + return input == null ? weekday : this.add(input - weekday, 'd'); + } + + function getSetISODayOfWeek (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); + } + + addFormatToken('H', ['HH', 2], 0, 'hour'); + addFormatToken('h', ['hh', 2], 0, function () { + return this.hours() % 12 || 12; + }); + + function meridiem (token, lowercase) { + addFormatToken(token, 0, 0, function () { + return this.localeData().meridiem(this.hours(), this.minutes(), lowercase); + }); + } + + meridiem('a', true); + meridiem('A', false); + + // ALIASES + + addUnitAlias('hour', 'h'); + + // PARSING + + function matchMeridiem (isStrict, locale) { + return locale._meridiemParse; + } + + addRegexToken('a', matchMeridiem); + addRegexToken('A', matchMeridiem); + addRegexToken('H', match1to2); + addRegexToken('h', match1to2); + addRegexToken('HH', match1to2, match2); + addRegexToken('hh', match1to2, match2); + + addParseToken(['H', 'HH'], HOUR); + addParseToken(['a', 'A'], function (input, array, config) { + config._isPm = config._locale.isPM(input); + config._meridiem = input; + }); + addParseToken(['h', 'hh'], function (input, array, config) { + array[HOUR] = toInt(input); + getParsingFlags(config).bigHour = true; + }); + + // LOCALES + + function localeIsPM (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); + } + + var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; + function localeMeridiem (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } + } + + + // MOMENTS + + // Setting the hour should keep the time, because the user explicitly + // specified which hour he wants. So trying to maintain the same hour (in + // a new timezone) makes sense. Adding/subtracting hours does not follow + // this rule. + var getSetHour = makeGetSet('Hours', true); + + addFormatToken('m', ['mm', 2], 0, 'minute'); + + // ALIASES + + addUnitAlias('minute', 'm'); + + // PARSING + + addRegexToken('m', match1to2); + addRegexToken('mm', match1to2, match2); + addParseToken(['m', 'mm'], MINUTE); + + // MOMENTS + + var getSetMinute = makeGetSet('Minutes', false); + + addFormatToken('s', ['ss', 2], 0, 'second'); + + // ALIASES + + addUnitAlias('second', 's'); + + // PARSING + + addRegexToken('s', match1to2); + addRegexToken('ss', match1to2, match2); + addParseToken(['s', 'ss'], SECOND); + + // MOMENTS + + var getSetSecond = makeGetSet('Seconds', false); + + addFormatToken('S', 0, 0, function () { + return ~~(this.millisecond() / 100); + }); + + addFormatToken(0, ['SS', 2], 0, function () { + return ~~(this.millisecond() / 10); + }); + + function millisecond__milliseconds (token) { + addFormatToken(0, [token, 3], 0, 'millisecond'); + } + + millisecond__milliseconds('SSS'); + millisecond__milliseconds('SSSS'); + + // ALIASES + + addUnitAlias('millisecond', 'ms'); + + // PARSING + + addRegexToken('S', match1to3, match1); + addRegexToken('SS', match1to3, match2); + addRegexToken('SSS', match1to3, match3); + addRegexToken('SSSS', matchUnsigned); + addParseToken(['S', 'SS', 'SSS', 'SSSS'], function (input, array) { + array[MILLISECOND] = toInt(('0.' + input) * 1000); + }); + + // MOMENTS + + var getSetMillisecond = makeGetSet('Milliseconds', false); + + addFormatToken('z', 0, 0, 'zoneAbbr'); + addFormatToken('zz', 0, 0, 'zoneName'); + + // MOMENTS + + function getZoneAbbr () { + return this._isUTC ? 'UTC' : ''; + } + + function getZoneName () { + return this._isUTC ? 'Coordinated Universal Time' : ''; + } + + var momentPrototype__proto = Moment.prototype; + + momentPrototype__proto.add = add_subtract__add; + momentPrototype__proto.calendar = moment_calendar__calendar; + momentPrototype__proto.clone = clone; + momentPrototype__proto.diff = diff; + momentPrototype__proto.endOf = endOf; + momentPrototype__proto.format = format; + momentPrototype__proto.from = from; + momentPrototype__proto.fromNow = fromNow; + momentPrototype__proto.to = to; + momentPrototype__proto.toNow = toNow; + momentPrototype__proto.get = getSet; + momentPrototype__proto.invalidAt = invalidAt; + momentPrototype__proto.isAfter = isAfter; + momentPrototype__proto.isBefore = isBefore; + momentPrototype__proto.isBetween = isBetween; + momentPrototype__proto.isSame = isSame; + momentPrototype__proto.isValid = moment_valid__isValid; + momentPrototype__proto.lang = lang; + momentPrototype__proto.locale = locale; + momentPrototype__proto.localeData = localeData; + momentPrototype__proto.max = prototypeMax; + momentPrototype__proto.min = prototypeMin; + momentPrototype__proto.parsingFlags = parsingFlags; + momentPrototype__proto.set = getSet; + momentPrototype__proto.startOf = startOf; + momentPrototype__proto.subtract = add_subtract__subtract; + momentPrototype__proto.toArray = toArray; + momentPrototype__proto.toDate = toDate; + momentPrototype__proto.toISOString = moment_format__toISOString; + momentPrototype__proto.toJSON = moment_format__toISOString; + momentPrototype__proto.toString = toString; + momentPrototype__proto.unix = unix; + momentPrototype__proto.valueOf = to_type__valueOf; + + // Year + momentPrototype__proto.year = getSetYear; + momentPrototype__proto.isLeapYear = getIsLeapYear; + + // Week Year + momentPrototype__proto.weekYear = getSetWeekYear; + momentPrototype__proto.isoWeekYear = getSetISOWeekYear; + + // Quarter + momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter; + + // Month + momentPrototype__proto.month = getSetMonth; + momentPrototype__proto.daysInMonth = getDaysInMonth; + + // Week + momentPrototype__proto.week = momentPrototype__proto.weeks = getSetWeek; + momentPrototype__proto.isoWeek = momentPrototype__proto.isoWeeks = getSetISOWeek; + momentPrototype__proto.weeksInYear = getWeeksInYear; + momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear; + + // Day + momentPrototype__proto.date = getSetDayOfMonth; + momentPrototype__proto.day = momentPrototype__proto.days = getSetDayOfWeek; + momentPrototype__proto.weekday = getSetLocaleDayOfWeek; + momentPrototype__proto.isoWeekday = getSetISODayOfWeek; + momentPrototype__proto.dayOfYear = getSetDayOfYear; + + // Hour + momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour; + + // Minute + momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute; + + // Second + momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond; + + // Millisecond + momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond; + + // Offset + momentPrototype__proto.utcOffset = getSetOffset; + momentPrototype__proto.utc = setOffsetToUTC; + momentPrototype__proto.local = setOffsetToLocal; + momentPrototype__proto.parseZone = setOffsetToParsedOffset; + momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset; + momentPrototype__proto.isDST = isDaylightSavingTime; + momentPrototype__proto.isDSTShifted = isDaylightSavingTimeShifted; + momentPrototype__proto.isLocal = isLocal; + momentPrototype__proto.isUtcOffset = isUtcOffset; + momentPrototype__proto.isUtc = isUtc; + momentPrototype__proto.isUTC = isUtc; + + // Timezone + momentPrototype__proto.zoneAbbr = getZoneAbbr; + momentPrototype__proto.zoneName = getZoneName; + + // Deprecations + momentPrototype__proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); + momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); + momentPrototype__proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); + momentPrototype__proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone); + + var momentPrototype = momentPrototype__proto; + + function moment__createUnix (input) { + return local__createLocal(input * 1000); + } + + function moment__createInZone () { + return local__createLocal.apply(null, arguments).parseZone(); + } + + var defaultCalendar = { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' + }; + + function locale_calendar__calendar (key, mom, now) { + var output = this._calendar[key]; + return typeof output === 'function' ? output.call(mom, now) : output; + } + + var defaultLongDateFormat = { + LTS : 'h:mm:ss A', + LT : 'h:mm A', + L : 'MM/DD/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY LT', + LLLL : 'dddd, MMMM D, YYYY LT' + }; + + function longDateFormat (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; + } + + var defaultInvalidDate = 'Invalid date'; + + function invalidDate () { + return this._invalidDate; + } + + var defaultOrdinal = '%d'; + var defaultOrdinalParse = /\d{1,2}/; + + function ordinal (number) { + return this._ordinal.replace('%d', number); + } + + function preParsePostFormat (string) { + return string; + } + + var defaultRelativeTime = { + 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' + }; + + function relative__relativeTime (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (typeof output === 'function') ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); + } + + function pastFuture (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); + } + + function locale_set__set (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (typeof prop === 'function') { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + // Lenient ordinal parsing accepts just a number in addition to + // number + (possibly) stuff coming from _ordinalParseLenient. + this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source); + } + + var prototype__proto = Locale.prototype; + + prototype__proto._calendar = defaultCalendar; + prototype__proto.calendar = locale_calendar__calendar; + prototype__proto._longDateFormat = defaultLongDateFormat; + prototype__proto.longDateFormat = longDateFormat; + prototype__proto._invalidDate = defaultInvalidDate; + prototype__proto.invalidDate = invalidDate; + prototype__proto._ordinal = defaultOrdinal; + prototype__proto.ordinal = ordinal; + prototype__proto._ordinalParse = defaultOrdinalParse; + prototype__proto.preparse = preParsePostFormat; + prototype__proto.postformat = preParsePostFormat; + prototype__proto._relativeTime = defaultRelativeTime; + prototype__proto.relativeTime = relative__relativeTime; + prototype__proto.pastFuture = pastFuture; + prototype__proto.set = locale_set__set; + + // Month + prototype__proto.months = localeMonths; + prototype__proto._months = defaultLocaleMonths; + prototype__proto.monthsShort = localeMonthsShort; + prototype__proto._monthsShort = defaultLocaleMonthsShort; + prototype__proto.monthsParse = localeMonthsParse; + + // Week + prototype__proto.week = localeWeek; + prototype__proto._week = defaultLocaleWeek; + prototype__proto.firstDayOfYear = localeFirstDayOfYear; + prototype__proto.firstDayOfWeek = localeFirstDayOfWeek; + + // Day of Week + prototype__proto.weekdays = localeWeekdays; + prototype__proto._weekdays = defaultLocaleWeekdays; + prototype__proto.weekdaysMin = localeWeekdaysMin; + prototype__proto._weekdaysMin = defaultLocaleWeekdaysMin; + prototype__proto.weekdaysShort = localeWeekdaysShort; + prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort; + prototype__proto.weekdaysParse = localeWeekdaysParse; + + // Hours + prototype__proto.isPM = localeIsPM; + prototype__proto._meridiemParse = defaultLocaleMeridiemParse; + prototype__proto.meridiem = localeMeridiem; + + function lists__get (format, index, field, setter) { + var locale = locale_locales__getLocale(); + var utc = create_utc__createUTC().set(setter, index); + return locale[field](utc, format); + } + + function list (format, index, field, count, setter) { + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + + if (index != null) { + return lists__get(format, index, field, setter); + } + + var i; + var out = []; + for (i = 0; i < count; i++) { + out[i] = lists__get(format, i, field, setter); + } + return out; + } + + function lists__listMonths (format, index) { + return list(format, index, 'months', 12, 'month'); + } + + function lists__listMonthsShort (format, index) { + return list(format, index, 'monthsShort', 12, 'month'); + } + + function lists__listWeekdays (format, index) { + return list(format, index, 'weekdays', 7, 'day'); + } + + function lists__listWeekdaysShort (format, index) { + return list(format, index, 'weekdaysShort', 7, 'day'); + } + + function lists__listWeekdaysMin (format, index) { + return list(format, index, 'weekdaysMin', 7, 'day'); + } + + locale_locales__getSetGlobalLocale('en', { + ordinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } + }); + + // Side effect imports + utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale); + utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale); + + var mathAbs = Math.abs; + + function duration_abs__abs () { + var data = this._data; + + this._milliseconds = mathAbs(this._milliseconds); + this._days = mathAbs(this._days); + this._months = mathAbs(this._months); + + data.milliseconds = mathAbs(data.milliseconds); + data.seconds = mathAbs(data.seconds); + data.minutes = mathAbs(data.minutes); + data.hours = mathAbs(data.hours); + data.months = mathAbs(data.months); + data.years = mathAbs(data.years); + + return this; + } + + function duration_add_subtract__addSubtract (duration, input, value, direction) { + var other = create__createDuration(input, value); + + duration._milliseconds += direction * other._milliseconds; + duration._days += direction * other._days; + duration._months += direction * other._months; + + return duration._bubble(); + } + + // supports only 2.0-style add(1, 's') or add(duration) + function duration_add_subtract__add (input, value) { + return duration_add_subtract__addSubtract(this, input, value, 1); + } + + // supports only 2.0-style subtract(1, 's') or subtract(duration) + function duration_add_subtract__subtract (input, value) { + return duration_add_subtract__addSubtract(this, input, value, -1); + } + + function bubble () { + var milliseconds = this._milliseconds; + var days = this._days; + var months = this._months; + var data = this._data; + var seconds, minutes, hours, years = 0; + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absFloor(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absFloor(seconds / 60); + data.minutes = minutes % 60; + + hours = absFloor(minutes / 60); + data.hours = hours % 24; + + days += absFloor(hours / 24); + + // Accurately convert days to years, assume start from year 0. + years = absFloor(daysToYears(days)); + days -= absFloor(yearsToDays(years)); + + // 30 days to a month + // TODO (iskren): Use anchor date (like 1st Jan) to compute this. + months += absFloor(days / 30); + days %= 30; + + // 12 months -> 1 year + years += absFloor(months / 12); + months %= 12; + + data.days = days; + data.months = months; + data.years = years; + + return this; + } + + function daysToYears (days) { + // 400 years have 146097 days (taking into account leap year rules) + return days * 400 / 146097; + } + + function yearsToDays (years) { + // years * 365 + absFloor(years / 4) - + // absFloor(years / 100) + absFloor(years / 400); + return years * 146097 / 400; + } + + function as (units) { + var days; + var months; + var milliseconds = this._milliseconds; + + units = normalizeUnits(units); + + if (units === 'month' || units === 'year') { + days = this._days + milliseconds / 864e5; + months = this._months + daysToYears(days) * 12; + return units === 'month' ? months : months / 12; + } else { + // handle milliseconds separately because of floating point math errors (issue #1867) + days = this._days + Math.round(yearsToDays(this._months / 12)); + switch (units) { + case 'week' : return days / 7 + milliseconds / 6048e5; + case 'day' : return days + milliseconds / 864e5; + case 'hour' : return days * 24 + milliseconds / 36e5; + case 'minute' : return days * 1440 + milliseconds / 6e4; + case 'second' : return days * 86400 + milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 864e5) + milliseconds; + default: throw new Error('Unknown unit ' + units); + } + } + } + + // TODO: Use this.as('ms')? + function duration_as__valueOf () { + return ( + this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6 + ); + } + + function makeAs (alias) { + return function () { + return this.as(alias); + }; + } + + var asMilliseconds = makeAs('ms'); + var asSeconds = makeAs('s'); + var asMinutes = makeAs('m'); + var asHours = makeAs('h'); + var asDays = makeAs('d'); + var asWeeks = makeAs('w'); + var asMonths = makeAs('M'); + var asYears = makeAs('y'); + + function duration_get__get (units) { + units = normalizeUnits(units); + return this[units + 's'](); + } + + function makeGetter(name) { + return function () { + return this._data[name]; + }; + } + + var duration_get__milliseconds = makeGetter('milliseconds'); + var seconds = makeGetter('seconds'); + var minutes = makeGetter('minutes'); + var hours = makeGetter('hours'); + var days = makeGetter('days'); + var months = makeGetter('months'); + var years = makeGetter('years'); + + function weeks () { + return absFloor(this.days() / 7); + } + + var round = Math.round; + var thresholds = { + s: 45, // seconds to minute + m: 45, // minutes to hour + h: 22, // hours to day + d: 26, // days to month + M: 11 // months to year + }; + + // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize + function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { + return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); + } + + function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) { + var duration = create__createDuration(posNegDuration).abs(); + var seconds = round(duration.as('s')); + var minutes = round(duration.as('m')); + var hours = round(duration.as('h')); + var days = round(duration.as('d')); + var months = round(duration.as('M')); + var years = round(duration.as('y')); + + var a = seconds < thresholds.s && ['s', seconds] || + minutes === 1 && ['m'] || + minutes < thresholds.m && ['mm', minutes] || + hours === 1 && ['h'] || + hours < thresholds.h && ['hh', hours] || + days === 1 && ['d'] || + days < thresholds.d && ['dd', days] || + months === 1 && ['M'] || + months < thresholds.M && ['MM', months] || + years === 1 && ['y'] || ['yy', years]; + + a[2] = withoutSuffix; + a[3] = +posNegDuration > 0; + a[4] = locale; + return substituteTimeAgo.apply(null, a); + } + + // This function allows you to set a threshold for relative time strings + function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) { + if (thresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return thresholds[threshold]; + } + thresholds[threshold] = limit; + return true; + } + + function humanize (withSuffix) { + var locale = this.localeData(); + var output = duration_humanize__relativeTime(this, !withSuffix, locale); + + if (withSuffix) { + output = locale.pastFuture(+this, output); + } + + return locale.postformat(output); + } + + var iso_string__abs = Math.abs; + + function iso_string__toISOString() { + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var Y = iso_string__abs(this.years()); + var M = iso_string__abs(this.months()); + var D = iso_string__abs(this.days()); + var h = iso_string__abs(this.hours()); + var m = iso_string__abs(this.minutes()); + var s = iso_string__abs(this.seconds() + this.milliseconds() / 1000); + var total = this.asSeconds(); + + if (!total) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + + return (total < 0 ? '-' : '') + + 'P' + + (Y ? Y + 'Y' : '') + + (M ? M + 'M' : '') + + (D ? D + 'D' : '') + + ((h || m || s) ? 'T' : '') + + (h ? h + 'H' : '') + + (m ? m + 'M' : '') + + (s ? s + 'S' : ''); + } + + var duration_prototype__proto = Duration.prototype; + + duration_prototype__proto.abs = duration_abs__abs; + duration_prototype__proto.add = duration_add_subtract__add; + duration_prototype__proto.subtract = duration_add_subtract__subtract; + duration_prototype__proto.as = as; + duration_prototype__proto.asMilliseconds = asMilliseconds; + duration_prototype__proto.asSeconds = asSeconds; + duration_prototype__proto.asMinutes = asMinutes; + duration_prototype__proto.asHours = asHours; + duration_prototype__proto.asDays = asDays; + duration_prototype__proto.asWeeks = asWeeks; + duration_prototype__proto.asMonths = asMonths; + duration_prototype__proto.asYears = asYears; + duration_prototype__proto.valueOf = duration_as__valueOf; + duration_prototype__proto._bubble = bubble; + duration_prototype__proto.get = duration_get__get; + duration_prototype__proto.milliseconds = duration_get__milliseconds; + duration_prototype__proto.seconds = seconds; + duration_prototype__proto.minutes = minutes; + duration_prototype__proto.hours = hours; + duration_prototype__proto.days = days; + duration_prototype__proto.weeks = weeks; + duration_prototype__proto.months = months; + duration_prototype__proto.years = years; + duration_prototype__proto.humanize = humanize; + duration_prototype__proto.toISOString = iso_string__toISOString; + duration_prototype__proto.toString = iso_string__toISOString; + duration_prototype__proto.toJSON = iso_string__toISOString; + duration_prototype__proto.locale = locale; + duration_prototype__proto.localeData = localeData; + + // Deprecations + duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString); + duration_prototype__proto.lang = lang; + + // Side effect imports + + addFormatToken('X', 0, 0, 'unix'); + addFormatToken('x', 0, 0, 'valueOf'); + + // PARSING + + addRegexToken('x', matchSigned); + addRegexToken('X', matchTimestamp); + addParseToken('X', function (input, array, config) { + config._d = new Date(parseFloat(input, 10) * 1000); + }); + addParseToken('x', function (input, array, config) { + config._d = new Date(toInt(input)); + }); + + // Side effect imports + + + utils_hooks__hooks.version = '2.10.3'; + + setHookCallback(local__createLocal); + + utils_hooks__hooks.fn = momentPrototype; + utils_hooks__hooks.min = min; + utils_hooks__hooks.max = max; + utils_hooks__hooks.utc = create_utc__createUTC; + utils_hooks__hooks.unix = moment__createUnix; + utils_hooks__hooks.months = lists__listMonths; + utils_hooks__hooks.isDate = isDate; + utils_hooks__hooks.locale = locale_locales__getSetGlobalLocale; + utils_hooks__hooks.invalid = valid__createInvalid; + utils_hooks__hooks.duration = create__createDuration; + utils_hooks__hooks.isMoment = isMoment; + utils_hooks__hooks.weekdays = lists__listWeekdays; + utils_hooks__hooks.parseZone = moment__createInZone; + utils_hooks__hooks.localeData = locale_locales__getLocale; + utils_hooks__hooks.isDuration = isDuration; + utils_hooks__hooks.monthsShort = lists__listMonthsShort; + utils_hooks__hooks.weekdaysMin = lists__listWeekdaysMin; + utils_hooks__hooks.defineLocale = defineLocale; + utils_hooks__hooks.weekdaysShort = lists__listWeekdaysShort; + utils_hooks__hooks.normalizeUnits = normalizeUnits; + utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold; + + var _moment = utils_hooks__hooks; + + return _moment; + +}));
\ No newline at end of file diff --git a/bower_components/moment/src/lib/create/check-overflow.js b/bower_components/moment/src/lib/create/check-overflow.js new file mode 100644 index 0000000..88a62ae --- /dev/null +++ b/bower_components/moment/src/lib/create/check-overflow.js @@ -0,0 +1,28 @@ +import { daysInMonth } from '../units/month'; +import { YEAR, MONTH, DATE, HOUR, MINUTE, SECOND, MILLISECOND } from '../units/constants'; +import getParsingFlags from '../create/parsing-flags'; + +export default function checkOverflow (m) { + var overflow; + var a = m._a; + + if (a && getParsingFlags(m).overflow === -2) { + overflow = + a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : + a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : + a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR : + a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : + a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : + a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : + -1; + + if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { + overflow = DATE; + } + + getParsingFlags(m).overflow = overflow; + } + + return m; +} + diff --git a/bower_components/moment/src/lib/create/date-from-array.js b/bower_components/moment/src/lib/create/date-from-array.js new file mode 100644 index 0000000..349eebc --- /dev/null +++ b/bower_components/moment/src/lib/create/date-from-array.js @@ -0,0 +1,19 @@ +export function createDate (y, m, d, h, M, s, ms) { + //can't just apply() to create a date: + //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply + var date = new Date(y, m, d, h, M, s, ms); + + //the date constructor doesn't accept years < 1970 + if (y < 1970) { + date.setFullYear(y); + } + return date; +} + +export function createUTCDate (y) { + var date = new Date(Date.UTC.apply(null, arguments)); + if (y < 1970) { + date.setUTCFullYear(y); + } + return date; +} diff --git a/bower_components/moment/src/lib/create/from-anything.js b/bower_components/moment/src/lib/create/from-anything.js new file mode 100644 index 0000000..4b836c0 --- /dev/null +++ b/bower_components/moment/src/lib/create/from-anything.js @@ -0,0 +1,93 @@ +import isArray from '../utils/is-array'; +import isDate from '../utils/is-date'; +import map from '../utils/map'; +import { createInvalid } from './valid'; +import { Moment, isMoment } from '../moment/constructor'; +import { getLocale } from '../locale/locales'; +import { hooks } from '../utils/hooks'; +import checkOverflow from './check-overflow'; + +import { configFromStringAndArray } from './from-string-and-array'; +import { configFromStringAndFormat } from './from-string-and-format'; +import { configFromString } from './from-string'; +import { configFromArray } from './from-array'; +import { configFromObject } from './from-object'; + +function createFromConfig (config) { + var input = config._i, + format = config._f, + res; + + config._locale = config._locale || getLocale(config._l); + + if (input === null || (format === undefined && input === '')) { + return createInvalid({nullInput: true}); + } + + if (typeof input === 'string') { + config._i = input = config._locale.preparse(input); + } + + if (isMoment(input)) { + return new Moment(checkOverflow(input)); + } else if (isArray(format)) { + configFromStringAndArray(config); + } else if (format) { + configFromStringAndFormat(config); + } else if (isDate(input)) { + config._d = input; + } else { + configFromInput(config); + } + + res = new Moment(checkOverflow(config)); + if (res._nextDay) { + // Adding is smart enough around DST + res.add(1, 'd'); + res._nextDay = undefined; + } + + return res; +} + +function configFromInput(config) { + var input = config._i; + if (input === undefined) { + config._d = new Date(); + } else if (isDate(input)) { + config._d = new Date(+input); + } else if (typeof input === 'string') { + configFromString(config); + } else if (isArray(input)) { + config._a = map(input.slice(0), function (obj) { + return parseInt(obj, 10); + }); + configFromArray(config); + } else if (typeof(input) === 'object') { + configFromObject(config); + } else if (typeof(input) === 'number') { + // from milliseconds + config._d = new Date(input); + } else { + hooks.createFromInputFallback(config); + } +} + +export function createLocalOrUTC (input, format, locale, strict, isUTC) { + var c = {}; + + if (typeof(locale) === 'boolean') { + strict = locale; + locale = undefined; + } + // object construction must be done this way. + // https://github.com/moment/moment/issues/1423 + c._isAMomentObject = true; + c._useUTC = c._isUTC = isUTC; + c._l = locale; + c._i = input; + c._f = format; + c._strict = strict; + + return createFromConfig(c); +} diff --git a/bower_components/moment/src/lib/create/from-array.js b/bower_components/moment/src/lib/create/from-array.js new file mode 100644 index 0000000..c4239cb --- /dev/null +++ b/bower_components/moment/src/lib/create/from-array.js @@ -0,0 +1,124 @@ +import { createDate, createUTCDate } from './date-from-array'; +import { daysInYear } from '../units/year'; +import { weekOfYear } from '../units/week'; +import { dayOfYearFromWeeks } from '../units/day-of-year'; +import { YEAR, MONTH, DATE, HOUR, MINUTE, SECOND, MILLISECOND } from '../units/constants'; +import { createLocal } from './local'; +import defaults from '../utils/defaults'; +import getParsingFlags from './parsing-flags'; + +function currentDateArray(config) { + var now = new Date(); + if (config._useUTC) { + return [now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()]; + } + return [now.getFullYear(), now.getMonth(), now.getDate()]; +} + +// 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] +export function configFromArray (config) { + var i, date, input = [], currentDate, yearToUse; + + if (config._d) { + return; + } + + currentDate = currentDateArray(config); + + //compute day of the year from weeks and weekdays + if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { + dayOfYearFromWeekInfo(config); + } + + //if the day of the year is set, figure out what it is + if (config._dayOfYear) { + yearToUse = defaults(config._a[YEAR], currentDate[YEAR]); + + if (config._dayOfYear > daysInYear(yearToUse)) { + getParsingFlags(config)._overflowDayOfYear = true; + } + + date = createUTCDate(yearToUse, 0, config._dayOfYear); + config._a[MONTH] = date.getUTCMonth(); + config._a[DATE] = date.getUTCDate(); + } + + // Default to current date. + // * if no year, month, day of month are given, default to today + // * if day of month is given, default month and year + // * if month is given, default only year + // * if year is given, don't default anything + for (i = 0; i < 3 && config._a[i] == null; ++i) { + config._a[i] = input[i] = currentDate[i]; + } + + // Zero out whatever was not defaulted, including time + for (; i < 7; i++) { + config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; + } + + // Check for 24:00:00.000 + if (config._a[HOUR] === 24 && + config._a[MINUTE] === 0 && + config._a[SECOND] === 0 && + config._a[MILLISECOND] === 0) { + config._nextDay = true; + config._a[HOUR] = 0; + } + + config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input); + // Apply timezone offset from input. The actual utcOffset can be changed + // with parseZone. + if (config._tzm != null) { + config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); + } + + if (config._nextDay) { + config._a[HOUR] = 24; + } +} + +function dayOfYearFromWeekInfo(config) { + var w, weekYear, week, weekday, dow, doy, temp; + + w = config._w; + if (w.GG != null || w.W != null || w.E != null) { + dow = 1; + doy = 4; + + // TODO: We need to take the current isoWeekYear, but that depends on + // how we interpret now (local, utc, fixed offset). So create + // a now version of current config (take local/utc/offset flags, and + // create now). + weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year); + week = defaults(w.W, 1); + weekday = defaults(w.E, 1); + } else { + dow = config._locale._week.dow; + doy = config._locale._week.doy; + + weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(createLocal(), dow, doy).year); + week = defaults(w.w, 1); + + if (w.d != null) { + // weekday -- low day numbers are considered next week + weekday = w.d; + if (weekday < dow) { + ++week; + } + } else if (w.e != null) { + // local weekday -- counting starts from begining of week + weekday = w.e + dow; + } else { + // default to begining of week + weekday = dow; + } + } + temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow); + + config._a[YEAR] = temp.year; + config._dayOfYear = temp.dayOfYear; +} diff --git a/bower_components/moment/src/lib/create/from-object.js b/bower_components/moment/src/lib/create/from-object.js new file mode 100644 index 0000000..af8e082 --- /dev/null +++ b/bower_components/moment/src/lib/create/from-object.js @@ -0,0 +1,13 @@ +import { normalizeObjectUnits } from '../units/aliases'; +import { configFromArray } from './from-array'; + +export function configFromObject(config) { + if (config._d) { + return; + } + + var i = normalizeObjectUnits(config._i); + config._a = [i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond]; + + configFromArray(config); +} diff --git a/bower_components/moment/src/lib/create/from-string-and-array.js b/bower_components/moment/src/lib/create/from-string-and-array.js new file mode 100644 index 0000000..1d8a7a8 --- /dev/null +++ b/bower_components/moment/src/lib/create/from-string-and-array.js @@ -0,0 +1,50 @@ +import { copyConfig } from '../moment/constructor'; +import { configFromStringAndFormat } from './from-string-and-format'; +import getParsingFlags from './parsing-flags'; +import { isValid } from './valid'; +import extend from '../utils/extend'; + +// date from string and array of format strings +export function configFromStringAndArray(config) { + var tempConfig, + bestMoment, + + scoreToBeat, + i, + currentScore; + + if (config._f.length === 0) { + getParsingFlags(config).invalidFormat = true; + config._d = new Date(NaN); + return; + } + + for (i = 0; i < config._f.length; i++) { + currentScore = 0; + tempConfig = copyConfig({}, config); + if (config._useUTC != null) { + tempConfig._useUTC = config._useUTC; + } + tempConfig._f = config._f[i]; + configFromStringAndFormat(tempConfig); + + if (!isValid(tempConfig)) { + continue; + } + + // if there is any input that was not parsed add a penalty for that format + currentScore += getParsingFlags(tempConfig).charsLeftOver; + + //or tokens + currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; + + getParsingFlags(tempConfig).score = currentScore; + + if (scoreToBeat == null || currentScore < scoreToBeat) { + scoreToBeat = currentScore; + bestMoment = tempConfig; + } + } + + extend(config, bestMoment || tempConfig); +} diff --git a/bower_components/moment/src/lib/create/from-string-and-format.js b/bower_components/moment/src/lib/create/from-string-and-format.js new file mode 100644 index 0000000..ae48b90 --- /dev/null +++ b/bower_components/moment/src/lib/create/from-string-and-format.js @@ -0,0 +1,102 @@ +import { configFromISO } from './from-string'; +import { configFromArray } from './from-array'; +import { getParseRegexForToken } from '../parse/regex'; +import { addTimeToArrayFromToken } from '../parse/token'; +import { expandFormat, formatTokenFunctions, formattingTokens } from '../format/format'; +import checkOverflow from './check-overflow'; +import { HOUR } from '../units/constants'; +import { hooks } from '../utils/hooks'; +import getParsingFlags from './parsing-flags'; + +// constant that refers to the ISO standard +hooks.ISO_8601 = function () {}; + +// date from string and format string +export function configFromStringAndFormat(config) { + // TODO: Move this to another part of the creation flow to prevent circular deps + if (config._f === hooks.ISO_8601) { + configFromISO(config); + return; + } + + config._a = []; + getParsingFlags(config).empty = true; + + // This array is used to make a Date, either with `new Date` or `Date.UTC` + var string = '' + config._i, + i, parsedInput, tokens, token, skipped, + stringLength = string.length, + totalParsedInputLength = 0; + + tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; + + for (i = 0; i < tokens.length; i++) { + token = tokens[i]; + parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; + if (parsedInput) { + skipped = string.substr(0, string.indexOf(parsedInput)); + if (skipped.length > 0) { + getParsingFlags(config).unusedInput.push(skipped); + } + string = string.slice(string.indexOf(parsedInput) + parsedInput.length); + totalParsedInputLength += parsedInput.length; + } + // don't parse if it's not a known token + if (formatTokenFunctions[token]) { + if (parsedInput) { + getParsingFlags(config).empty = false; + } + else { + getParsingFlags(config).unusedTokens.push(token); + } + addTimeToArrayFromToken(token, parsedInput, config); + } + else if (config._strict && !parsedInput) { + getParsingFlags(config).unusedTokens.push(token); + } + } + + // add remaining unparsed input length to the string + getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength; + if (string.length > 0) { + getParsingFlags(config).unusedInput.push(string); + } + + // clear _12h flag if hour is <= 12 + if (getParsingFlags(config).bigHour === true && + config._a[HOUR] <= 12 && + config._a[HOUR] > 0) { + getParsingFlags(config).bigHour = undefined; + } + // handle meridiem + config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); + + configFromArray(config); + checkOverflow(config); +} + + +function meridiemFixWrap (locale, hour, meridiem) { + var isPm; + + if (meridiem == null) { + // nothing to do + return hour; + } + if (locale.meridiemHour != null) { + return locale.meridiemHour(hour, meridiem); + } else if (locale.isPM != null) { + // Fallback + isPm = locale.isPM(meridiem); + if (isPm && hour < 12) { + hour += 12; + } + if (!isPm && hour === 12) { + hour = 0; + } + return hour; + } else { + // this is not supposed to happen + return hour; + } +} diff --git a/bower_components/moment/src/lib/create/from-string.js b/bower_components/moment/src/lib/create/from-string.js new file mode 100644 index 0000000..4bd6d59 --- /dev/null +++ b/bower_components/moment/src/lib/create/from-string.js @@ -0,0 +1,83 @@ +import { matchOffset } from '../parse/regex'; +import { configFromStringAndFormat } from './from-string-and-format'; +import { hooks } from '../utils/hooks'; +import { deprecate } from '../utils/deprecate'; +import getParsingFlags from './parsing-flags'; + +// iso 8601 regex +// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00) +var isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/; + +var isoDates = [ + ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/], + ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/], + ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/], + ['GGGG-[W]WW', /\d{4}-W\d{2}/], + ['YYYY-DDD', /\d{4}-\d{3}/] +]; + +// iso time formats and regexes +var isoTimes = [ + ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/], + ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], + ['HH:mm', /(T| )\d\d:\d\d/], + ['HH', /(T| )\d\d/] +]; + +var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; + +// date from iso format +export function configFromISO(config) { + var i, l, + string = config._i, + match = isoRegex.exec(string); + + if (match) { + getParsingFlags(config).iso = true; + for (i = 0, l = isoDates.length; i < l; i++) { + if (isoDates[i][1].exec(string)) { + // match[5] should be 'T' or undefined + config._f = isoDates[i][0] + (match[6] || ' '); + break; + } + } + for (i = 0, l = isoTimes.length; i < l; i++) { + if (isoTimes[i][1].exec(string)) { + config._f += isoTimes[i][0]; + break; + } + } + if (string.match(matchOffset)) { + config._f += 'Z'; + } + configFromStringAndFormat(config); + } else { + config._isValid = false; + } +} + +// date from iso format or fallback +export function configFromString(config) { + var matched = aspNetJsonRegex.exec(config._i); + + if (matched !== null) { + config._d = new Date(+matched[1]); + return; + } + + configFromISO(config); + if (config._isValid === false) { + delete config._isValid; + hooks.createFromInputFallback(config); + } +} + +hooks.createFromInputFallback = deprecate( + 'moment construction falls back to js Date. This is ' + + 'discouraged and will be removed in upcoming major ' + + 'release. Please refer to ' + + 'https://github.com/moment/moment/issues/1407 for more info.', + function (config) { + config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); + } +); diff --git a/bower_components/moment/src/lib/create/local.js b/bower_components/moment/src/lib/create/local.js new file mode 100644 index 0000000..88c1e26 --- /dev/null +++ b/bower_components/moment/src/lib/create/local.js @@ -0,0 +1,5 @@ +import { createLocalOrUTC } from './from-anything'; + +export function createLocal (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, false); +} diff --git a/bower_components/moment/src/lib/create/parsing-flags.js b/bower_components/moment/src/lib/create/parsing-flags.js new file mode 100644 index 0000000..2bfbcb3 --- /dev/null +++ b/bower_components/moment/src/lib/create/parsing-flags.js @@ -0,0 +1,22 @@ +function defaultParsingFlags() { + // We need to deep clone this object. + return { + empty : false, + unusedTokens : [], + unusedInput : [], + overflow : -2, + charsLeftOver : 0, + nullInput : false, + invalidMonth : null, + invalidFormat : false, + userInvalidated : false, + iso : false + }; +} + +export default function getParsingFlags(m) { + if (m._pf == null) { + m._pf = defaultParsingFlags(); + } + return m._pf; +} diff --git a/bower_components/moment/src/lib/create/utc.js b/bower_components/moment/src/lib/create/utc.js new file mode 100644 index 0000000..9613953 --- /dev/null +++ b/bower_components/moment/src/lib/create/utc.js @@ -0,0 +1,5 @@ +import { createLocalOrUTC } from './from-anything'; + +export function createUTC (input, format, locale, strict) { + return createLocalOrUTC(input, format, locale, strict, true).utc(); +} diff --git a/bower_components/moment/src/lib/create/valid.js b/bower_components/moment/src/lib/create/valid.js new file mode 100644 index 0000000..89204f8 --- /dev/null +++ b/bower_components/moment/src/lib/create/valid.js @@ -0,0 +1,36 @@ +import extend from '../utils/extend'; +import { createUTC } from './utc'; +import getParsingFlags from '../create/parsing-flags'; + +export function isValid(m) { + if (m._isValid == null) { + var flags = getParsingFlags(m); + m._isValid = !isNaN(m._d.getTime()) && + flags.overflow < 0 && + !flags.empty && + !flags.invalidMonth && + !flags.nullInput && + !flags.invalidFormat && + !flags.userInvalidated; + + if (m._strict) { + m._isValid = m._isValid && + flags.charsLeftOver === 0 && + flags.unusedTokens.length === 0 && + flags.bigHour === undefined; + } + } + return m._isValid; +} + +export function createInvalid (flags) { + var m = createUTC(NaN); + if (flags != null) { + extend(getParsingFlags(m), flags); + } + else { + getParsingFlags(m).userInvalidated = true; + } + + return m; +} diff --git a/bower_components/moment/src/lib/duration/abs.js b/bower_components/moment/src/lib/duration/abs.js new file mode 100644 index 0000000..103a4cf --- /dev/null +++ b/bower_components/moment/src/lib/duration/abs.js @@ -0,0 +1,18 @@ +var mathAbs = Math.abs; + +export function abs () { + var data = this._data; + + this._milliseconds = mathAbs(this._milliseconds); + this._days = mathAbs(this._days); + this._months = mathAbs(this._months); + + data.milliseconds = mathAbs(data.milliseconds); + data.seconds = mathAbs(data.seconds); + data.minutes = mathAbs(data.minutes); + data.hours = mathAbs(data.hours); + data.months = mathAbs(data.months); + data.years = mathAbs(data.years); + + return this; +} diff --git a/bower_components/moment/src/lib/duration/add-subtract.js b/bower_components/moment/src/lib/duration/add-subtract.js new file mode 100644 index 0000000..3b44e18 --- /dev/null +++ b/bower_components/moment/src/lib/duration/add-subtract.js @@ -0,0 +1,21 @@ +import { createDuration } from './create'; + +function addSubtract (duration, input, value, direction) { + var other = createDuration(input, value); + + duration._milliseconds += direction * other._milliseconds; + duration._days += direction * other._days; + duration._months += direction * other._months; + + return duration._bubble(); +} + +// supports only 2.0-style add(1, 's') or add(duration) +export function add (input, value) { + return addSubtract(this, input, value, 1); +} + +// supports only 2.0-style subtract(1, 's') or subtract(duration) +export function subtract (input, value) { + return addSubtract(this, input, value, -1); +} diff --git a/bower_components/moment/src/lib/duration/as.js b/bower_components/moment/src/lib/duration/as.js new file mode 100644 index 0000000..258c501 --- /dev/null +++ b/bower_components/moment/src/lib/duration/as.js @@ -0,0 +1,55 @@ +import { daysToYears, yearsToDays } from './bubble'; +import { normalizeUnits } from '../units/aliases'; +import toInt from '../utils/to-int'; + +export function as (units) { + var days; + var months; + var milliseconds = this._milliseconds; + + units = normalizeUnits(units); + + if (units === 'month' || units === 'year') { + days = this._days + milliseconds / 864e5; + months = this._months + daysToYears(days) * 12; + return units === 'month' ? months : months / 12; + } else { + // handle milliseconds separately because of floating point math errors (issue #1867) + days = this._days + Math.round(yearsToDays(this._months / 12)); + switch (units) { + case 'week' : return days / 7 + milliseconds / 6048e5; + case 'day' : return days + milliseconds / 864e5; + case 'hour' : return days * 24 + milliseconds / 36e5; + case 'minute' : return days * 1440 + milliseconds / 6e4; + case 'second' : return days * 86400 + milliseconds / 1000; + // Math.floor prevents floating point math errors here + case 'millisecond': return Math.floor(days * 864e5) + milliseconds; + default: throw new Error('Unknown unit ' + units); + } + } +} + +// TODO: Use this.as('ms')? +export function valueOf () { + return ( + this._milliseconds + + this._days * 864e5 + + (this._months % 12) * 2592e6 + + toInt(this._months / 12) * 31536e6 + ); +} + +function makeAs (alias) { + return function () { + return this.as(alias); + }; +} + +export var asMilliseconds = makeAs('ms'); +export var asSeconds = makeAs('s'); +export var asMinutes = makeAs('m'); +export var asHours = makeAs('h'); +export var asDays = makeAs('d'); +export var asWeeks = makeAs('w'); +export var asMonths = makeAs('M'); +export var asYears = makeAs('y'); diff --git a/bower_components/moment/src/lib/duration/bubble.js b/bower_components/moment/src/lib/duration/bubble.js new file mode 100644 index 0000000..3dae6b2 --- /dev/null +++ b/bower_components/moment/src/lib/duration/bubble.js @@ -0,0 +1,54 @@ +import absFloor from '../utils/abs-floor'; + +export function bubble () { + var milliseconds = this._milliseconds; + var days = this._days; + var months = this._months; + var data = this._data; + var seconds, minutes, hours, years = 0; + + // The following code bubbles up values, see the tests for + // examples of what that means. + data.milliseconds = milliseconds % 1000; + + seconds = absFloor(milliseconds / 1000); + data.seconds = seconds % 60; + + minutes = absFloor(seconds / 60); + data.minutes = minutes % 60; + + hours = absFloor(minutes / 60); + data.hours = hours % 24; + + days += absFloor(hours / 24); + + // Accurately convert days to years, assume start from year 0. + years = absFloor(daysToYears(days)); + days -= absFloor(yearsToDays(years)); + + // 30 days to a month + // TODO (iskren): Use anchor date (like 1st Jan) to compute this. + months += absFloor(days / 30); + days %= 30; + + // 12 months -> 1 year + years += absFloor(months / 12); + months %= 12; + + data.days = days; + data.months = months; + data.years = years; + + return this; +} + +export function daysToYears (days) { + // 400 years have 146097 days (taking into account leap year rules) + return days * 400 / 146097; +} + +export function yearsToDays (years) { + // years * 365 + absFloor(years / 4) - + // absFloor(years / 100) + absFloor(years / 400); + return years * 146097 / 400; +} diff --git a/bower_components/moment/src/lib/duration/constructor.js b/bower_components/moment/src/lib/duration/constructor.js new file mode 100644 index 0000000..884c6f8 --- /dev/null +++ b/bower_components/moment/src/lib/duration/constructor.js @@ -0,0 +1,41 @@ +import { normalizeObjectUnits } from '../units/aliases'; +import { getLocale } from '../locale/locales'; + +export function Duration (duration) { + var normalizedInput = normalizeObjectUnits(duration), + years = normalizedInput.year || 0, + quarters = normalizedInput.quarter || 0, + months = normalizedInput.month || 0, + weeks = normalizedInput.week || 0, + days = normalizedInput.day || 0, + hours = normalizedInput.hour || 0, + minutes = normalizedInput.minute || 0, + seconds = normalizedInput.second || 0, + milliseconds = normalizedInput.millisecond || 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 + + quarters * 3 + + years * 12; + + this._data = {}; + + this._locale = getLocale(); + + this._bubble(); +} + +export function isDuration (obj) { + return obj instanceof Duration; +} diff --git a/bower_components/moment/src/lib/duration/create.js b/bower_components/moment/src/lib/duration/create.js new file mode 100644 index 0000000..15f05de --- /dev/null +++ b/bower_components/moment/src/lib/duration/create.js @@ -0,0 +1,113 @@ +import { Duration, isDuration } from './constructor'; +import toInt from '../utils/to-int'; +import hasOwnProp from '../utils/has-own-prop'; +import { DATE, HOUR, MINUTE, SECOND, MILLISECOND } from '../units/constants'; +import { cloneWithOffset } from '../units/offset'; +import { createLocal } from '../create/local'; + +// ASP.NET json date format regex +var aspNetRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/; + +// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html +// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere +var isoRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/; + +export function createDuration (input, key) { + var duration = input, + // matching against regexp is expensive, do it on demand + match = null, + sign, + ret, + diffRes; + + if (isDuration(input)) { + duration = { + ms : input._milliseconds, + d : input._days, + M : input._months + }; + } else if (typeof input === 'number') { + duration = {}; + if (key) { + duration[key] = input; + } else { + duration.milliseconds = input; + } + } else if (!!(match = aspNetRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : 0, + d : toInt(match[DATE]) * sign, + h : toInt(match[HOUR]) * sign, + m : toInt(match[MINUTE]) * sign, + s : toInt(match[SECOND]) * sign, + ms : toInt(match[MILLISECOND]) * sign + }; + } else if (!!(match = isoRegex.exec(input))) { + sign = (match[1] === '-') ? -1 : 1; + duration = { + y : parseIso(match[2], sign), + M : parseIso(match[3], sign), + d : parseIso(match[4], sign), + h : parseIso(match[5], sign), + m : parseIso(match[6], sign), + s : parseIso(match[7], sign), + w : parseIso(match[8], sign) + }; + } else if (duration == null) {// checks for null or undefined + duration = {}; + } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) { + diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to)); + + duration = {}; + duration.ms = diffRes.milliseconds; + duration.M = diffRes.months; + } + + ret = new Duration(duration); + + if (isDuration(input) && hasOwnProp(input, '_locale')) { + ret._locale = input._locale; + } + + return ret; +} + +createDuration.fn = Duration.prototype; + +function parseIso (inp, sign) { + // We'd normally use ~~inp for this, but unfortunately it also + // converts floats to ints. + // inp may be undefined, so careful calling replace on it. + var res = inp && parseFloat(inp.replace(',', '.')); + // apply sign while we're at it + return (isNaN(res) ? 0 : res) * sign; +} + +function positiveMomentsDifference(base, other) { + var res = {milliseconds: 0, months: 0}; + + res.months = other.month() - base.month() + + (other.year() - base.year()) * 12; + if (base.clone().add(res.months, 'M').isAfter(other)) { + --res.months; + } + + res.milliseconds = +other - +(base.clone().add(res.months, 'M')); + + return res; +} + +function momentsDifference(base, other) { + var res; + other = cloneWithOffset(other, base); + if (base.isBefore(other)) { + res = positiveMomentsDifference(base, other); + } else { + res = positiveMomentsDifference(other, base); + res.milliseconds = -res.milliseconds; + res.months = -res.months; + } + + return res; +} diff --git a/bower_components/moment/src/lib/duration/duration.js b/bower_components/moment/src/lib/duration/duration.js new file mode 100644 index 0000000..24440bb --- /dev/null +++ b/bower_components/moment/src/lib/duration/duration.js @@ -0,0 +1,12 @@ +// Side effect imports +import './prototype'; + +import { createDuration } from './create'; +import { isDuration } from './constructor'; +import { getSetRelativeTimeThreshold } from './humanize'; + +export { + createDuration, + isDuration, + getSetRelativeTimeThreshold +}; diff --git a/bower_components/moment/src/lib/duration/get.js b/bower_components/moment/src/lib/duration/get.js new file mode 100644 index 0000000..6dafacd --- /dev/null +++ b/bower_components/moment/src/lib/duration/get.js @@ -0,0 +1,25 @@ +import { normalizeUnits } from '../units/aliases'; +import absFloor from '../utils/abs-floor'; + +export function get (units) { + units = normalizeUnits(units); + return this[units + 's'](); +} + +function makeGetter(name) { + return function () { + return this._data[name]; + }; +} + +export var milliseconds = makeGetter('milliseconds'); +export var seconds = makeGetter('seconds'); +export var minutes = makeGetter('minutes'); +export var hours = makeGetter('hours'); +export var days = makeGetter('days'); +export var months = makeGetter('months'); +export var years = makeGetter('years'); + +export function weeks () { + return absFloor(this.days() / 7); +} diff --git a/bower_components/moment/src/lib/duration/humanize.js b/bower_components/moment/src/lib/duration/humanize.js new file mode 100644 index 0000000..d6dd83b --- /dev/null +++ b/bower_components/moment/src/lib/duration/humanize.js @@ -0,0 +1,64 @@ +import { createDuration } from './create'; + +var round = Math.round; +var thresholds = { + s: 45, // seconds to minute + m: 45, // minutes to hour + h: 22, // hours to day + d: 26, // days to month + M: 11 // months to year +}; + +// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize +function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { + return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); +} + +function relativeTime (posNegDuration, withoutSuffix, locale) { + var duration = createDuration(posNegDuration).abs(); + var seconds = round(duration.as('s')); + var minutes = round(duration.as('m')); + var hours = round(duration.as('h')); + var days = round(duration.as('d')); + var months = round(duration.as('M')); + var years = round(duration.as('y')); + + var a = seconds < thresholds.s && ['s', seconds] || + minutes === 1 && ['m'] || + minutes < thresholds.m && ['mm', minutes] || + hours === 1 && ['h'] || + hours < thresholds.h && ['hh', hours] || + days === 1 && ['d'] || + days < thresholds.d && ['dd', days] || + months === 1 && ['M'] || + months < thresholds.M && ['MM', months] || + years === 1 && ['y'] || ['yy', years]; + + a[2] = withoutSuffix; + a[3] = +posNegDuration > 0; + a[4] = locale; + return substituteTimeAgo.apply(null, a); +} + +// This function allows you to set a threshold for relative time strings +export function getSetRelativeTimeThreshold (threshold, limit) { + if (thresholds[threshold] === undefined) { + return false; + } + if (limit === undefined) { + return thresholds[threshold]; + } + thresholds[threshold] = limit; + return true; +} + +export function humanize (withSuffix) { + var locale = this.localeData(); + var output = relativeTime(this, !withSuffix, locale); + + if (withSuffix) { + output = locale.pastFuture(+this, output); + } + + return locale.postformat(output); +} diff --git a/bower_components/moment/src/lib/duration/iso-string.js b/bower_components/moment/src/lib/duration/iso-string.js new file mode 100644 index 0000000..2670a9d --- /dev/null +++ b/bower_components/moment/src/lib/duration/iso-string.js @@ -0,0 +1,28 @@ +var abs = Math.abs; + +export function toISOString() { + // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js + var Y = abs(this.years()); + var M = abs(this.months()); + var D = abs(this.days()); + var h = abs(this.hours()); + var m = abs(this.minutes()); + var s = abs(this.seconds() + this.milliseconds() / 1000); + var total = this.asSeconds(); + + if (!total) { + // this is the same as C#'s (Noda) and python (isodate)... + // but not other JS (goog.date) + return 'P0D'; + } + + return (total < 0 ? '-' : '') + + 'P' + + (Y ? Y + 'Y' : '') + + (M ? M + 'M' : '') + + (D ? D + 'D' : '') + + ((h || m || s) ? 'T' : '') + + (h ? h + 'H' : '') + + (m ? m + 'M' : '') + + (s ? s + 'S' : ''); +} diff --git a/bower_components/moment/src/lib/duration/prototype.js b/bower_components/moment/src/lib/duration/prototype.js new file mode 100644 index 0000000..0257ff9 --- /dev/null +++ b/bower_components/moment/src/lib/duration/prototype.js @@ -0,0 +1,48 @@ +import { Duration } from './constructor'; + +var proto = Duration.prototype; + +import { abs } from './abs'; +import { add, subtract } from './add-subtract'; +import { as, asMilliseconds, asSeconds, asMinutes, asHours, asDays, asWeeks, asMonths, asYears, valueOf } from './as'; +import { bubble } from './bubble'; +import { get, milliseconds, seconds, minutes, hours, days, months, years, weeks } from './get'; +import { humanize } from './humanize'; +import { toISOString } from './iso-string'; +import { lang, locale, localeData } from '../moment/locale'; + +proto.abs = abs; +proto.add = add; +proto.subtract = subtract; +proto.as = as; +proto.asMilliseconds = asMilliseconds; +proto.asSeconds = asSeconds; +proto.asMinutes = asMinutes; +proto.asHours = asHours; +proto.asDays = asDays; +proto.asWeeks = asWeeks; +proto.asMonths = asMonths; +proto.asYears = asYears; +proto.valueOf = valueOf; +proto._bubble = bubble; +proto.get = get; +proto.milliseconds = milliseconds; +proto.seconds = seconds; +proto.minutes = minutes; +proto.hours = hours; +proto.days = days; +proto.weeks = weeks; +proto.months = months; +proto.years = years; +proto.humanize = humanize; +proto.toISOString = toISOString; +proto.toString = toISOString; +proto.toJSON = toISOString; +proto.locale = locale; +proto.localeData = localeData; + +// Deprecations +import { deprecate } from '../utils/deprecate'; + +proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString); +proto.lang = lang; diff --git a/bower_components/moment/src/lib/format/format.js b/bower_components/moment/src/lib/format/format.js new file mode 100644 index 0000000..565da01 --- /dev/null +++ b/bower_components/moment/src/lib/format/format.js @@ -0,0 +1,95 @@ +import zeroFill from '../utils/zero-fill'; + +export var formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g; + +var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; + +var formatFunctions = {}; + +export var formatTokenFunctions = {}; + +// token: 'M' +// padded: ['MM', 2] +// ordinal: 'Mo' +// callback: function () { this.month() + 1 } +export function addFormatToken (token, padded, ordinal, callback) { + var func = callback; + if (typeof callback === 'string') { + func = function () { + return this[callback](); + }; + } + if (token) { + formatTokenFunctions[token] = func; + } + if (padded) { + formatTokenFunctions[padded[0]] = function () { + return zeroFill(func.apply(this, arguments), padded[1], padded[2]); + }; + } + if (ordinal) { + formatTokenFunctions[ordinal] = function () { + return this.localeData().ordinal(func.apply(this, arguments), token); + }; + } +} + +function removeFormattingTokens(input) { + if (input.match(/\[[\s\S]/)) { + 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 +export function formatMoment(m, format) { + if (!m.isValid()) { + return m.localeData().invalidDate(); + } + + format = expandFormat(format, m.localeData()); + + if (!formatFunctions[format]) { + formatFunctions[format] = makeFormatFunction(format); + } + + return formatFunctions[format](m); +} + +export function expandFormat(format, locale) { + var i = 5; + + function replaceLongDateFormatTokens(input) { + return locale.longDateFormat(input) || input; + } + + localFormattingTokens.lastIndex = 0; + while (i >= 0 && localFormattingTokens.test(format)) { + format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); + localFormattingTokens.lastIndex = 0; + i -= 1; + } + + return format; +} + diff --git a/bower_components/moment/src/lib/locale/calendar.js b/bower_components/moment/src/lib/locale/calendar.js new file mode 100644 index 0000000..22545b9 --- /dev/null +++ b/bower_components/moment/src/lib/locale/calendar.js @@ -0,0 +1,13 @@ +export var defaultCalendar = { + sameDay : '[Today at] LT', + nextDay : '[Tomorrow at] LT', + nextWeek : 'dddd [at] LT', + lastDay : '[Yesterday at] LT', + lastWeek : '[Last] dddd [at] LT', + sameElse : 'L' +}; + +export function calendar (key, mom, now) { + var output = this._calendar[key]; + return typeof output === 'function' ? output.call(mom, now) : output; +} diff --git a/bower_components/moment/src/lib/locale/constructor.js b/bower_components/moment/src/lib/locale/constructor.js new file mode 100644 index 0000000..2c17b5d --- /dev/null +++ b/bower_components/moment/src/lib/locale/constructor.js @@ -0,0 +1,2 @@ +export function Locale() { +} diff --git a/bower_components/moment/src/lib/locale/en.js b/bower_components/moment/src/lib/locale/en.js new file mode 100644 index 0000000..20964cd --- /dev/null +++ b/bower_components/moment/src/lib/locale/en.js @@ -0,0 +1,15 @@ +import './prototype'; +import { getSetGlobalLocale } from './locales'; +import toInt from '../utils/to-int'; + +getSetGlobalLocale('en', { + ordinalParse: /\d{1,2}(th|st|nd|rd)/, + ordinal : function (number) { + var b = number % 10, + output = (toInt(number % 100 / 10) === 1) ? 'th' : + (b === 1) ? 'st' : + (b === 2) ? 'nd' : + (b === 3) ? 'rd' : 'th'; + return number + output; + } +}); diff --git a/bower_components/moment/src/lib/locale/formats.js b/bower_components/moment/src/lib/locale/formats.js new file mode 100644 index 0000000..22b75ad --- /dev/null +++ b/bower_components/moment/src/lib/locale/formats.js @@ -0,0 +1,19 @@ +export var defaultLongDateFormat = { + LTS : 'h:mm:ss A', + LT : 'h:mm A', + L : 'MM/DD/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY LT', + LLLL : 'dddd, MMMM D, YYYY LT' +}; + +export function longDateFormat (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; +} diff --git a/bower_components/moment/src/lib/locale/invalid.js b/bower_components/moment/src/lib/locale/invalid.js new file mode 100644 index 0000000..e909633 --- /dev/null +++ b/bower_components/moment/src/lib/locale/invalid.js @@ -0,0 +1,5 @@ +export var defaultInvalidDate = 'Invalid date'; + +export function invalidDate () { + return this._invalidDate; +} diff --git a/bower_components/moment/src/lib/locale/lists.js b/bower_components/moment/src/lib/locale/lists.js new file mode 100644 index 0000000..ea0161a --- /dev/null +++ b/bower_components/moment/src/lib/locale/lists.js @@ -0,0 +1,48 @@ +import { getLocale } from './locales'; +import { createUTC } from '../create/utc'; + +function get (format, index, field, setter) { + var locale = getLocale(); + var utc = createUTC().set(setter, index); + return locale[field](utc, format); +} + +function list (format, index, field, count, setter) { + if (typeof format === 'number') { + index = format; + format = undefined; + } + + format = format || ''; + + if (index != null) { + return get(format, index, field, setter); + } + + var i; + var out = []; + for (i = 0; i < count; i++) { + out[i] = get(format, i, field, setter); + } + return out; +} + +export function listMonths (format, index) { + return list(format, index, 'months', 12, 'month'); +} + +export function listMonthsShort (format, index) { + return list(format, index, 'monthsShort', 12, 'month'); +} + +export function listWeekdays (format, index) { + return list(format, index, 'weekdays', 7, 'day'); +} + +export function listWeekdaysShort (format, index) { + return list(format, index, 'weekdaysShort', 7, 'day'); +} + +export function listWeekdaysMin (format, index) { + return list(format, index, 'weekdaysMin', 7, 'day'); +} diff --git a/bower_components/moment/src/lib/locale/locale.js b/bower_components/moment/src/lib/locale/locale.js new file mode 100644 index 0000000..2fc3c46 --- /dev/null +++ b/bower_components/moment/src/lib/locale/locale.js @@ -0,0 +1,35 @@ +// Side effect imports +import './prototype'; + +import { + getSetGlobalLocale, + defineLocale, + getLocale +} from './locales'; + +import { + listMonths, + listMonthsShort, + listWeekdays, + listWeekdaysShort, + listWeekdaysMin +} from './lists'; + +export { + getSetGlobalLocale, + defineLocale, + getLocale, + listMonths, + listMonthsShort, + listWeekdays, + listWeekdaysShort, + listWeekdaysMin +}; + +import { deprecate } from '../utils/deprecate'; +import { hooks } from '../utils/hooks'; + +hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale); +hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale); + +import './en'; diff --git a/bower_components/moment/src/lib/locale/locales.js b/bower_components/moment/src/lib/locale/locales.js new file mode 100644 index 0000000..0e58ded --- /dev/null +++ b/bower_components/moment/src/lib/locale/locales.js @@ -0,0 +1,119 @@ +import isArray from '../utils/is-array'; +import compareArrays from '../utils/compare-arrays'; +import { Locale } from './constructor'; + +// internal storage for locale config files +var locales = {}; +var globalLocale; + +function normalizeLocale(key) { + return key ? key.toLowerCase().replace('_', '-') : key; +} + +// pick the locale from the array +// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each +// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root +function chooseLocale(names) { + var i = 0, j, next, locale, split; + + while (i < names.length) { + split = normalizeLocale(names[i]).split('-'); + j = split.length; + next = normalizeLocale(names[i + 1]); + next = next ? next.split('-') : null; + while (j > 0) { + locale = loadLocale(split.slice(0, j).join('-')); + if (locale) { + return locale; + } + if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { + //the next array item is better than a shallower substring of this one + break; + } + j--; + } + i++; + } + return null; +} + +function loadLocale(name) { + var oldLocale = null; + // TODO: Find a better way to register and load all the locales in Node + if (!locales[name] && typeof module !== 'undefined' && + module && module.exports) { + try { + oldLocale = globalLocale._abbr; + require('./locale/' + name); + // because defineLocale currently also sets the global locale, we + // want to undo that for lazy loaded locales + getSetGlobalLocale(oldLocale); + } catch (e) { } + } + return locales[name]; +} + +// This function will load locale and then set the global locale. If +// no arguments are passed in, it will simply return the current global +// locale key. +export function getSetGlobalLocale (key, values) { + var data; + if (key) { + if (typeof values === 'undefined') { + data = getLocale(key); + } + else { + data = defineLocale(key, values); + } + + if (data) { + // moment.duration._locale = moment._locale = data; + globalLocale = data; + } + } + + return globalLocale._abbr; +} + +export function defineLocale (name, values) { + if (values !== null) { + values.abbr = name; + if (!locales[name]) { + locales[name] = new Locale(); + } + locales[name].set(values); + + // backwards compat for now: also set the locale + getSetGlobalLocale(name); + + return locales[name]; + } else { + // useful for testing + delete locales[name]; + return null; + } +} + +// returns locale data +export function getLocale (key) { + var locale; + + if (key && key._locale && key._locale._abbr) { + key = key._locale._abbr; + } + + if (!key) { + return globalLocale; + } + + if (!isArray(key)) { + //short-circuit everything else + locale = loadLocale(key); + if (locale) { + return locale; + } + key = [key]; + } + + return chooseLocale(key); +} diff --git a/bower_components/moment/src/lib/locale/ordinal.js b/bower_components/moment/src/lib/locale/ordinal.js new file mode 100644 index 0000000..0028aca --- /dev/null +++ b/bower_components/moment/src/lib/locale/ordinal.js @@ -0,0 +1,7 @@ +export var defaultOrdinal = '%d'; +export var defaultOrdinalParse = /\d{1,2}/; + +export function ordinal (number) { + return this._ordinal.replace('%d', number); +} + diff --git a/bower_components/moment/src/lib/locale/pre-post-format.js b/bower_components/moment/src/lib/locale/pre-post-format.js new file mode 100644 index 0000000..10ed205 --- /dev/null +++ b/bower_components/moment/src/lib/locale/pre-post-format.js @@ -0,0 +1,3 @@ +export function preParsePostFormat (string) { + return string; +} diff --git a/bower_components/moment/src/lib/locale/prototype.js b/bower_components/moment/src/lib/locale/prototype.js new file mode 100644 index 0000000..ed02d4f --- /dev/null +++ b/bower_components/moment/src/lib/locale/prototype.js @@ -0,0 +1,70 @@ +import { Locale } from './constructor'; + +var proto = Locale.prototype; + +import { defaultCalendar, calendar } from './calendar'; +import { defaultLongDateFormat, longDateFormat } from './formats'; +import { defaultInvalidDate, invalidDate } from './invalid'; +import { defaultOrdinal, ordinal, defaultOrdinalParse } from './ordinal'; +import { preParsePostFormat } from './pre-post-format'; +import { defaultRelativeTime, relativeTime, pastFuture } from './relative'; +import { set } from './set'; + +proto._calendar = defaultCalendar; +proto.calendar = calendar; +proto._longDateFormat = defaultLongDateFormat; +proto.longDateFormat = longDateFormat; +proto._invalidDate = defaultInvalidDate; +proto.invalidDate = invalidDate; +proto._ordinal = defaultOrdinal; +proto.ordinal = ordinal; +proto._ordinalParse = defaultOrdinalParse; +proto.preparse = preParsePostFormat; +proto.postformat = preParsePostFormat; +proto._relativeTime = defaultRelativeTime; +proto.relativeTime = relativeTime; +proto.pastFuture = pastFuture; +proto.set = set; + +// Month +import { + localeMonthsParse, + defaultLocaleMonths, localeMonths, + defaultLocaleMonthsShort, localeMonthsShort +} from '../units/month'; + +proto.months = localeMonths; +proto._months = defaultLocaleMonths; +proto.monthsShort = localeMonthsShort; +proto._monthsShort = defaultLocaleMonthsShort; +proto.monthsParse = localeMonthsParse; + +// Week +import { localeWeek, defaultLocaleWeek, localeFirstDayOfYear, localeFirstDayOfWeek } from '../units/week'; +proto.week = localeWeek; +proto._week = defaultLocaleWeek; +proto.firstDayOfYear = localeFirstDayOfYear; +proto.firstDayOfWeek = localeFirstDayOfWeek; + +// Day of Week +import { + localeWeekdaysParse, + defaultLocaleWeekdays, localeWeekdays, + defaultLocaleWeekdaysMin, localeWeekdaysMin, + defaultLocaleWeekdaysShort, localeWeekdaysShort +} from '../units/day-of-week'; + +proto.weekdays = localeWeekdays; +proto._weekdays = defaultLocaleWeekdays; +proto.weekdaysMin = localeWeekdaysMin; +proto._weekdaysMin = defaultLocaleWeekdaysMin; +proto.weekdaysShort = localeWeekdaysShort; +proto._weekdaysShort = defaultLocaleWeekdaysShort; +proto.weekdaysParse = localeWeekdaysParse; + +// Hours +import { localeIsPM, defaultLocaleMeridiemParse, localeMeridiem } from '../units/hour'; + +proto.isPM = localeIsPM; +proto._meridiemParse = defaultLocaleMeridiemParse; +proto.meridiem = localeMeridiem; diff --git a/bower_components/moment/src/lib/locale/relative.js b/bower_components/moment/src/lib/locale/relative.js new file mode 100644 index 0000000..5986a67 --- /dev/null +++ b/bower_components/moment/src/lib/locale/relative.js @@ -0,0 +1,27 @@ +export var defaultRelativeTime = { + 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' +}; + +export function relativeTime (number, withoutSuffix, string, isFuture) { + var output = this._relativeTime[string]; + return (typeof output === 'function') ? + output(number, withoutSuffix, string, isFuture) : + output.replace(/%d/i, number); +} + +export function pastFuture (diff, output) { + var format = this._relativeTime[diff > 0 ? 'future' : 'past']; + return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); +} diff --git a/bower_components/moment/src/lib/locale/set.js b/bower_components/moment/src/lib/locale/set.js new file mode 100644 index 0000000..32db2ad --- /dev/null +++ b/bower_components/moment/src/lib/locale/set.js @@ -0,0 +1,14 @@ +export function set (config) { + var prop, i; + for (i in config) { + prop = config[i]; + if (typeof prop === 'function') { + this[i] = prop; + } else { + this['_' + i] = prop; + } + } + // Lenient ordinal parsing accepts just a number in addition to + // number + (possibly) stuff coming from _ordinalParseLenient. + this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source); +} diff --git a/bower_components/moment/src/lib/moment/add-subtract.js b/bower_components/moment/src/lib/moment/add-subtract.js new file mode 100644 index 0000000..ebfe674 --- /dev/null +++ b/bower_components/moment/src/lib/moment/add-subtract.js @@ -0,0 +1,46 @@ +import { get, set } from './get-set'; +import { setMonth } from '../units/month'; +import { createDuration } from '../duration/create'; +import { deprecateSimple } from '../utils/deprecate'; +import { hooks } from '../utils/hooks'; + +// TODO: remove 'name' arg after deprecation is removed +function createAdder(direction, name) { + return function (val, period) { + var dur, tmp; + //invert the arguments, but complain about it + if (period !== null && !isNaN(+period)) { + deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).'); + tmp = val; val = period; period = tmp; + } + + val = typeof val === 'string' ? +val : val; + dur = createDuration(val, period); + addSubtract(this, dur, direction); + return this; + }; +} + +export function addSubtract (mom, duration, isAdding, updateOffset) { + var milliseconds = duration._milliseconds, + days = duration._days, + months = duration._months; + updateOffset = updateOffset == null ? true : updateOffset; + + if (milliseconds) { + mom._d.setTime(+mom._d + milliseconds * isAdding); + } + if (days) { + set(mom, 'Date', get(mom, 'Date') + days * isAdding); + } + if (months) { + setMonth(mom, get(mom, 'Month') + months * isAdding); + } + if (updateOffset) { + hooks.updateOffset(mom, days || months); + } +} + +export var add = createAdder(1, 'add'); +export var subtract = createAdder(-1, 'subtract'); + diff --git a/bower_components/moment/src/lib/moment/calendar.js b/bower_components/moment/src/lib/moment/calendar.js new file mode 100644 index 0000000..66d70ad --- /dev/null +++ b/bower_components/moment/src/lib/moment/calendar.js @@ -0,0 +1,17 @@ +import { createLocal } from '../create/local'; +import { cloneWithOffset } from '../units/offset'; + +export function calendar (time) { + // We want to compare the start of today, vs this. + // Getting start-of-today depends on whether we're local/utc/offset or not. + var now = time || createLocal(), + sod = cloneWithOffset(now, this).startOf('day'), + diff = this.diff(sod, '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.localeData().calendar(format, this, createLocal(now))); +} diff --git a/bower_components/moment/src/lib/moment/clone.js b/bower_components/moment/src/lib/moment/clone.js new file mode 100644 index 0000000..d96b328 --- /dev/null +++ b/bower_components/moment/src/lib/moment/clone.js @@ -0,0 +1,5 @@ +import { Moment } from './constructor'; + +export function clone () { + return new Moment(this); +} diff --git a/bower_components/moment/src/lib/moment/compare.js b/bower_components/moment/src/lib/moment/compare.js new file mode 100644 index 0000000..b663473 --- /dev/null +++ b/bower_components/moment/src/lib/moment/compare.js @@ -0,0 +1,43 @@ +import { isMoment } from './constructor'; +import { normalizeUnits } from '../units/aliases'; +import { createLocal } from '../create/local'; + +export function isAfter (input, units) { + var inputMs; + units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); + if (units === 'millisecond') { + input = isMoment(input) ? input : createLocal(input); + return +this > +input; + } else { + inputMs = isMoment(input) ? +input : +createLocal(input); + return inputMs < +this.clone().startOf(units); + } +} + +export function isBefore (input, units) { + var inputMs; + units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond'); + if (units === 'millisecond') { + input = isMoment(input) ? input : createLocal(input); + return +this < +input; + } else { + inputMs = isMoment(input) ? +input : +createLocal(input); + return +this.clone().endOf(units) < inputMs; + } +} + +export function isBetween (from, to, units) { + return this.isAfter(from, units) && this.isBefore(to, units); +} + +export function isSame (input, units) { + var inputMs; + units = normalizeUnits(units || 'millisecond'); + if (units === 'millisecond') { + input = isMoment(input) ? input : createLocal(input); + return +this === +input; + } else { + inputMs = +createLocal(input); + return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units)); + } +} diff --git a/bower_components/moment/src/lib/moment/constructor.js b/bower_components/moment/src/lib/moment/constructor.js new file mode 100644 index 0000000..f735593 --- /dev/null +++ b/bower_components/moment/src/lib/moment/constructor.js @@ -0,0 +1,73 @@ +import { hooks } from '../utils/hooks'; +import hasOwnProp from '../utils/has-own-prop'; +import getParsingFlags from '../create/parsing-flags'; + +// Plugins that add properties should also add the key here (null value), +// so we can properly clone ourselves. +var momentProperties = hooks.momentProperties = []; + +export function copyConfig(to, from) { + var i, prop, val; + + if (typeof from._isAMomentObject !== 'undefined') { + to._isAMomentObject = from._isAMomentObject; + } + if (typeof from._i !== 'undefined') { + to._i = from._i; + } + if (typeof from._f !== 'undefined') { + to._f = from._f; + } + if (typeof from._l !== 'undefined') { + to._l = from._l; + } + if (typeof from._strict !== 'undefined') { + to._strict = from._strict; + } + if (typeof from._tzm !== 'undefined') { + to._tzm = from._tzm; + } + if (typeof from._isUTC !== 'undefined') { + to._isUTC = from._isUTC; + } + if (typeof from._offset !== 'undefined') { + to._offset = from._offset; + } + if (typeof from._pf !== 'undefined') { + to._pf = getParsingFlags(from); + } + if (typeof from._locale !== 'undefined') { + to._locale = from._locale; + } + + if (momentProperties.length > 0) { + for (i in momentProperties) { + prop = momentProperties[i]; + val = from[prop]; + if (typeof val !== 'undefined') { + to[prop] = val; + } + } + } + + return to; +} + +var updateInProgress = false; + +// Moment prototype object +export function Moment(config) { + copyConfig(this, config); + this._d = new Date(+config._d); + // Prevent infinite loop in case updateOffset creates new moment + // objects. + if (updateInProgress === false) { + updateInProgress = true; + hooks.updateOffset(this); + updateInProgress = false; + } +} + +export function isMoment (obj) { + return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); +} diff --git a/bower_components/moment/src/lib/moment/diff.js b/bower_components/moment/src/lib/moment/diff.js new file mode 100644 index 0000000..2c16d1d --- /dev/null +++ b/bower_components/moment/src/lib/moment/diff.js @@ -0,0 +1,49 @@ +import absFloor from '../utils/abs-floor'; +import { cloneWithOffset } from '../units/offset'; +import { normalizeUnits } from '../units/aliases'; + +export function diff (input, units, asFloat) { + var that = cloneWithOffset(input, this), + zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4, + delta, output; + + units = normalizeUnits(units); + + if (units === 'year' || units === 'month' || units === 'quarter') { + output = monthDiff(this, that); + if (units === 'quarter') { + output = output / 3; + } else if (units === 'year') { + output = output / 12; + } + } else { + delta = this - that; + output = units === 'second' ? delta / 1e3 : // 1000 + units === 'minute' ? delta / 6e4 : // 1000 * 60 + units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60 + units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst + units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst + delta; + } + return asFloat ? output : absFloor(output); +} + +function monthDiff (a, b) { + // difference in months + var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), + // b is in (anchor - 1 month, anchor + 1 month) + anchor = a.clone().add(wholeMonthDiff, 'months'), + anchor2, adjust; + + if (b - anchor < 0) { + anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor - anchor2); + } else { + anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); + // linear across the month + adjust = (b - anchor) / (anchor2 - anchor); + } + + return -(wholeMonthDiff + adjust); +} diff --git a/bower_components/moment/src/lib/moment/format.js b/bower_components/moment/src/lib/moment/format.js new file mode 100644 index 0000000..4939f38 --- /dev/null +++ b/bower_components/moment/src/lib/moment/format.js @@ -0,0 +1,27 @@ +import { formatMoment } from '../format/format'; +import { hooks } from '../utils/hooks'; + +hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; + +export function toString () { + return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); +} + +export function toISOString () { + var m = this.clone().utc(); + if (0 < m.year() && m.year() <= 9999) { + if ('function' === typeof Date.prototype.toISOString) { + // native implementation is ~50x faster, use it when we can + return this.toDate().toISOString(); + } else { + return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } + } else { + return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); + } +} + +export function format (inputString) { + var output = formatMoment(this, inputString || hooks.defaultFormat); + return this.localeData().postformat(output); +} diff --git a/bower_components/moment/src/lib/moment/from.js b/bower_components/moment/src/lib/moment/from.js new file mode 100644 index 0000000..c6a5449 --- /dev/null +++ b/bower_components/moment/src/lib/moment/from.js @@ -0,0 +1,13 @@ +import { createDuration } from '../duration/create'; +import { createLocal } from '../create/local'; + +export function from (time, withoutSuffix) { + if (!this.isValid()) { + return this.localeData().invalidDate(); + } + return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); +} + +export function fromNow (withoutSuffix) { + return this.from(createLocal(), withoutSuffix); +} diff --git a/bower_components/moment/src/lib/moment/get-set.js b/bower_components/moment/src/lib/moment/get-set.js new file mode 100644 index 0000000..0f2be60 --- /dev/null +++ b/bower_components/moment/src/lib/moment/get-set.js @@ -0,0 +1,39 @@ +import { normalizeUnits } from '../units/aliases'; +import { hooks } from '../utils/hooks'; + +export function makeGetSet (unit, keepTime) { + return function (value) { + if (value != null) { + set(this, unit, value); + hooks.updateOffset(this, keepTime); + return this; + } else { + return get(this, unit); + } + }; +} + +export function get (mom, unit) { + return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit](); +} + +export function set (mom, unit, value) { + return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); +} + +// MOMENTS + +export function getSet (units, value) { + var unit; + if (typeof units === 'object') { + for (unit in units) { + this.set(unit, units[unit]); + } + } else { + units = normalizeUnits(units); + if (typeof this[units] === 'function') { + return this[units](value); + } + } + return this; +} diff --git a/bower_components/moment/src/lib/moment/locale.js b/bower_components/moment/src/lib/moment/locale.js new file mode 100644 index 0000000..fb46e65 --- /dev/null +++ b/bower_components/moment/src/lib/moment/locale.js @@ -0,0 +1,34 @@ +import { getLocale } from '../locale/locales'; +import { deprecate } from '../utils/deprecate'; + +// If passed a locale key, it will set the locale for this +// instance. Otherwise, it will return the locale configuration +// variables for this instance. +export function locale (key) { + var newLocaleData; + + if (key === undefined) { + return this._locale._abbr; + } else { + newLocaleData = getLocale(key); + if (newLocaleData != null) { + this._locale = newLocaleData; + } + return this; + } +} + +export var lang = deprecate( + 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', + function (key) { + if (key === undefined) { + return this.localeData(); + } else { + return this.locale(key); + } + } +); + +export function localeData () { + return this._locale; +} diff --git a/bower_components/moment/src/lib/moment/min-max.js b/bower_components/moment/src/lib/moment/min-max.js new file mode 100644 index 0000000..c4a88d2 --- /dev/null +++ b/bower_components/moment/src/lib/moment/min-max.js @@ -0,0 +1,54 @@ +import { deprecate } from '../utils/deprecate'; +import isArray from '../utils/is-array'; +import { createLocal } from '../create/local'; + +export var prototypeMin = deprecate( + 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548', + function () { + var other = createLocal.apply(null, arguments); + return other < this ? this : other; + } + ); + +export var prototypeMax = deprecate( + 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548', + function () { + var other = createLocal.apply(null, arguments); + return other > this ? this : other; + } +); + +// Pick a moment m from moments so that m[fn](other) is true for all +// other. This relies on the function fn to be transitive. +// +// moments should either be an array of moment objects or an array, whose +// first element is an array of moment objects. +function pickBy(fn, moments) { + var res, i; + if (moments.length === 1 && isArray(moments[0])) { + moments = moments[0]; + } + if (!moments.length) { + return createLocal(); + } + res = moments[0]; + for (i = 1; i < moments.length; ++i) { + if (moments[i][fn](res)) { + res = moments[i]; + } + } + return res; +} + +// TODO: Use [].sort instead? +export function min () { + var args = [].slice.call(arguments, 0); + + return pickBy('isBefore', args); +} + +export function max () { + var args = [].slice.call(arguments, 0); + + return pickBy('isAfter', args); +} diff --git a/bower_components/moment/src/lib/moment/moment.js b/bower_components/moment/src/lib/moment/moment.js new file mode 100644 index 0000000..cf73b9f --- /dev/null +++ b/bower_components/moment/src/lib/moment/moment.js @@ -0,0 +1,26 @@ +import { createLocal } from '../create/local'; +import { createUTC } from '../create/utc'; +import { createInvalid } from '../create/valid'; +import { isMoment } from './constructor'; +import { min, max } from './min-max'; +import momentPrototype from './prototype'; + +function createUnix (input) { + return createLocal(input * 1000); +} + +function createInZone () { + return createLocal.apply(null, arguments).parseZone(); +} + +export { + min, + max, + isMoment, + createUTC, + createUnix, + createLocal, + createInZone, + createInvalid, + momentPrototype +}; diff --git a/bower_components/moment/src/lib/moment/prototype.js b/bower_components/moment/src/lib/moment/prototype.js new file mode 100644 index 0000000..5601bc0 --- /dev/null +++ b/bower_components/moment/src/lib/moment/prototype.js @@ -0,0 +1,144 @@ +import { Moment } from './constructor'; + +var proto = Moment.prototype; + +import { add, subtract } from './add-subtract'; +import { calendar } from './calendar'; +import { clone } from './clone'; +import { isBefore, isBetween, isSame, isAfter } from './compare'; +import { diff } from './diff'; +import { format, toString, toISOString } from './format'; +import { from, fromNow } from './from'; +import { to, toNow } from './to'; +import { getSet } from './get-set'; +import { locale, localeData, lang } from './locale'; +import { prototypeMin, prototypeMax } from './min-max'; +import { startOf, endOf } from './start-end-of'; +import { valueOf, toDate, toArray, unix } from './to-type'; +import { isValid, parsingFlags, invalidAt } from './valid'; + +proto.add = add; +proto.calendar = calendar; +proto.clone = clone; +proto.diff = diff; +proto.endOf = endOf; +proto.format = format; +proto.from = from; +proto.fromNow = fromNow; +proto.to = to; +proto.toNow = toNow; +proto.get = getSet; +proto.invalidAt = invalidAt; +proto.isAfter = isAfter; +proto.isBefore = isBefore; +proto.isBetween = isBetween; +proto.isSame = isSame; +proto.isValid = isValid; +proto.lang = lang; +proto.locale = locale; +proto.localeData = localeData; +proto.max = prototypeMax; +proto.min = prototypeMin; +proto.parsingFlags = parsingFlags; +proto.set = getSet; +proto.startOf = startOf; +proto.subtract = subtract; +proto.toArray = toArray; +proto.toDate = toDate; +proto.toISOString = toISOString; +proto.toJSON = toISOString; +proto.toString = toString; +proto.unix = unix; +proto.valueOf = valueOf; + +// Year +import { getSetYear, getIsLeapYear } from '../units/year'; +proto.year = getSetYear; +proto.isLeapYear = getIsLeapYear; + +// Week Year +import { getSetWeekYear, getSetISOWeekYear, getWeeksInYear, getISOWeeksInYear } from '../units/week-year'; +proto.weekYear = getSetWeekYear; +proto.isoWeekYear = getSetISOWeekYear; + +// Quarter +import { getSetQuarter } from '../units/quarter'; +proto.quarter = proto.quarters = getSetQuarter; + +// Month +import { getSetMonth, getDaysInMonth } from '../units/month'; +proto.month = getSetMonth; +proto.daysInMonth = getDaysInMonth; + +// Week +import { getSetWeek, getSetISOWeek } from '../units/week'; +proto.week = proto.weeks = getSetWeek; +proto.isoWeek = proto.isoWeeks = getSetISOWeek; +proto.weeksInYear = getWeeksInYear; +proto.isoWeeksInYear = getISOWeeksInYear; + +// Day +import { getSetDayOfMonth } from '../units/day-of-month'; +import { getSetDayOfWeek, getSetISODayOfWeek, getSetLocaleDayOfWeek } from '../units/day-of-week'; +import { getSetDayOfYear } from '../units/day-of-year'; +proto.date = getSetDayOfMonth; +proto.day = proto.days = getSetDayOfWeek; +proto.weekday = getSetLocaleDayOfWeek; +proto.isoWeekday = getSetISODayOfWeek; +proto.dayOfYear = getSetDayOfYear; + +// Hour +import { getSetHour } from '../units/hour'; +proto.hour = proto.hours = getSetHour; + +// Minute +import { getSetMinute } from '../units/minute'; +proto.minute = proto.minutes = getSetMinute; + +// Second +import { getSetSecond } from '../units/second'; +proto.second = proto.seconds = getSetSecond; + +// Millisecond +import { getSetMillisecond } from '../units/millisecond'; +proto.millisecond = proto.milliseconds = getSetMillisecond; + +// Offset +import { + getSetOffset, + setOffsetToUTC, + setOffsetToLocal, + setOffsetToParsedOffset, + hasAlignedHourOffset, + isDaylightSavingTime, + isDaylightSavingTimeShifted, + getSetZone, + isLocal, + isUtcOffset, + isUtc +} from '../units/offset'; +proto.utcOffset = getSetOffset; +proto.utc = setOffsetToUTC; +proto.local = setOffsetToLocal; +proto.parseZone = setOffsetToParsedOffset; +proto.hasAlignedHourOffset = hasAlignedHourOffset; +proto.isDST = isDaylightSavingTime; +proto.isDSTShifted = isDaylightSavingTimeShifted; +proto.isLocal = isLocal; +proto.isUtcOffset = isUtcOffset; +proto.isUtc = isUtc; +proto.isUTC = isUtc; + +// Timezone +import { getZoneAbbr, getZoneName } from '../units/timezone'; +proto.zoneAbbr = getZoneAbbr; +proto.zoneName = getZoneName; + +// Deprecations +import { deprecate } from '../utils/deprecate'; +proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); +proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); +proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); +proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone); + +export default proto; diff --git a/bower_components/moment/src/lib/moment/start-end-of.js b/bower_components/moment/src/lib/moment/start-end-of.js new file mode 100644 index 0000000..193c8b4 --- /dev/null +++ b/bower_components/moment/src/lib/moment/start-end-of.js @@ -0,0 +1,52 @@ +import { normalizeUnits } from '../units/aliases'; + +export function startOf (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 'quarter': + case 'month': + this.date(1); + /* falls through */ + case 'week': + case 'isoWeek': + 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); + } + + // weeks are a special case + if (units === 'week') { + this.weekday(0); + } + if (units === 'isoWeek') { + this.isoWeekday(1); + } + + // quarters are also special + if (units === 'quarter') { + this.month(Math.floor(this.month() / 3) * 3); + } + + return this; +} + +export function endOf (units) { + units = normalizeUnits(units); + if (units === undefined || units === 'millisecond') { + return this; + } + return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); +} diff --git a/bower_components/moment/src/lib/moment/to-type.js b/bower_components/moment/src/lib/moment/to-type.js new file mode 100644 index 0000000..edc1338 --- /dev/null +++ b/bower_components/moment/src/lib/moment/to-type.js @@ -0,0 +1,16 @@ +export function valueOf () { + return +this._d - ((this._offset || 0) * 60000); +} + +export function unix () { + return Math.floor(+this / 1000); +} + +export function toDate () { + return this._offset ? new Date(+this) : this._d; +} + +export function toArray () { + var m = this; + return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()]; +} diff --git a/bower_components/moment/src/lib/moment/to.js b/bower_components/moment/src/lib/moment/to.js new file mode 100644 index 0000000..d9eccfd --- /dev/null +++ b/bower_components/moment/src/lib/moment/to.js @@ -0,0 +1,13 @@ +import { createDuration } from '../duration/create'; +import { createLocal } from '../create/local'; + +export function to (time, withoutSuffix) { + if (!this.isValid()) { + return this.localeData().invalidDate(); + } + return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix); +} + +export function toNow (withoutSuffix) { + return this.to(createLocal(), withoutSuffix); +} diff --git a/bower_components/moment/src/lib/moment/valid.js b/bower_components/moment/src/lib/moment/valid.js new file mode 100644 index 0000000..6c00742 --- /dev/null +++ b/bower_components/moment/src/lib/moment/valid.js @@ -0,0 +1,15 @@ +import { isValid as _isValid } from '../create/valid'; +import extend from '../utils/extend'; +import getParsingFlags from '../create/parsing-flags'; + +export function isValid () { + return _isValid(this); +} + +export function parsingFlags () { + return extend({}, getParsingFlags(this)); +} + +export function invalidAt () { + return getParsingFlags(this).overflow; +} diff --git a/bower_components/moment/src/lib/parse/regex.js b/bower_components/moment/src/lib/parse/regex.js new file mode 100644 index 0000000..23091a0 --- /dev/null +++ b/bower_components/moment/src/lib/parse/regex.js @@ -0,0 +1,44 @@ +export var match1 = /\d/; // 0 - 9 +export var match2 = /\d\d/; // 00 - 99 +export var match3 = /\d{3}/; // 000 - 999 +export var match4 = /\d{4}/; // 0000 - 9999 +export var match6 = /[+-]?\d{6}/; // -999999 - 999999 +export var match1to2 = /\d\d?/; // 0 - 99 +export var match1to3 = /\d{1,3}/; // 0 - 999 +export var match1to4 = /\d{1,4}/; // 0 - 9999 +export var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 + +export var matchUnsigned = /\d+/; // 0 - inf +export var matchSigned = /[+-]?\d+/; // -inf - inf + +export var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z + +export var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 + +// any word (or two) characters or numbers including two/three word month in arabic. +export var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i; + +import hasOwnProp from '../utils/has-own-prop'; + +var regexes = {}; + +export function addRegexToken (token, regex, strictRegex) { + regexes[token] = typeof regex === 'function' ? regex : function (isStrict) { + return (isStrict && strictRegex) ? strictRegex : regex; + }; +} + +export function getParseRegexForToken (token, config) { + if (!hasOwnProp(regexes, token)) { + return new RegExp(unescapeFormat(token)); + } + + return regexes[token](config._strict, config._locale); +} + +// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript +function unescapeFormat(s) { + return s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { + return p1 || p2 || p3 || p4; + }).replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); +} diff --git a/bower_components/moment/src/lib/parse/token.js b/bower_components/moment/src/lib/parse/token.js new file mode 100644 index 0000000..781b9cf --- /dev/null +++ b/bower_components/moment/src/lib/parse/token.js @@ -0,0 +1,32 @@ +import hasOwnProp from '../utils/has-own-prop'; +import toInt from '../utils/to-int'; + +var tokens = {}; + +export function addParseToken (token, callback) { + var i, func = callback; + if (typeof token === 'string') { + token = [token]; + } + if (typeof callback === 'number') { + func = function (input, array) { + array[callback] = toInt(input); + }; + } + for (i = 0; i < token.length; i++) { + tokens[token[i]] = func; + } +} + +export function addWeekParseToken (token, callback) { + addParseToken(token, function (input, array, config, token) { + config._w = config._w || {}; + callback(input, config._w, config, token); + }); +} + +export function addTimeToArrayFromToken(token, input, config) { + if (input != null && hasOwnProp(tokens, token)) { + tokens[token](input, config._a, config, token); + } +} diff --git a/bower_components/moment/src/lib/units/aliases.js b/bower_components/moment/src/lib/units/aliases.js new file mode 100644 index 0000000..4ad5133 --- /dev/null +++ b/bower_components/moment/src/lib/units/aliases.js @@ -0,0 +1,29 @@ +import hasOwnProp from '../utils/has-own-prop'; + +var aliases = {}; + +export function addUnitAlias (unit, shorthand) { + var lowerCase = unit.toLowerCase(); + aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit; +} + +export function normalizeUnits(units) { + return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined; +} + +export function normalizeObjectUnits(inputObject) { + var normalizedInput = {}, + normalizedProp, + prop; + + for (prop in inputObject) { + if (hasOwnProp(inputObject, prop)) { + normalizedProp = normalizeUnits(prop); + if (normalizedProp) { + normalizedInput[normalizedProp] = inputObject[prop]; + } + } + } + + return normalizedInput; +} diff --git a/bower_components/moment/src/lib/units/constants.js b/bower_components/moment/src/lib/units/constants.js new file mode 100644 index 0000000..588e70d --- /dev/null +++ b/bower_components/moment/src/lib/units/constants.js @@ -0,0 +1,7 @@ +export var YEAR = 0; +export var MONTH = 1; +export var DATE = 2; +export var HOUR = 3; +export var MINUTE = 4; +export var SECOND = 5; +export var MILLISECOND = 6; diff --git a/bower_components/moment/src/lib/units/day-of-month.js b/bower_components/moment/src/lib/units/day-of-month.js new file mode 100644 index 0000000..dc32acc --- /dev/null +++ b/bower_components/moment/src/lib/units/day-of-month.js @@ -0,0 +1,32 @@ +import { makeGetSet } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addRegexToken, match1to2, match2 } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { DATE } from './constants'; +import toInt from '../utils/to-int'; + +// FORMATTING + +addFormatToken('D', ['DD', 2], 'Do', 'date'); + +// ALIASES + +addUnitAlias('date', 'D'); + +// PARSING + +addRegexToken('D', match1to2); +addRegexToken('DD', match1to2, match2); +addRegexToken('Do', function (isStrict, locale) { + return isStrict ? locale._ordinalParse : locale._ordinalParseLenient; +}); + +addParseToken(['D', 'DD'], DATE); +addParseToken('Do', function (input, array) { + array[DATE] = toInt(input.match(match1to2)[0], 10); +}); + +// MOMENTS + +export var getSetDayOfMonth = makeGetSet('Date', true); diff --git a/bower_components/moment/src/lib/units/day-of-week.js b/bower_components/moment/src/lib/units/day-of-week.js new file mode 100644 index 0000000..7af2408 --- /dev/null +++ b/bower_components/moment/src/lib/units/day-of-week.js @@ -0,0 +1,134 @@ +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addRegexToken, match1to2, matchWord } from '../parse/regex'; +import { addWeekParseToken } from '../parse/token'; +import toInt from '../utils/to-int'; +import { createLocal } from '../create/local'; +import getParsingFlags from '../create/parsing-flags'; + +// FORMATTING + +addFormatToken('d', 0, 'do', 'day'); + +addFormatToken('dd', 0, 0, function (format) { + return this.localeData().weekdaysMin(this, format); +}); + +addFormatToken('ddd', 0, 0, function (format) { + return this.localeData().weekdaysShort(this, format); +}); + +addFormatToken('dddd', 0, 0, function (format) { + return this.localeData().weekdays(this, format); +}); + +addFormatToken('e', 0, 0, 'weekday'); +addFormatToken('E', 0, 0, 'isoWeekday'); + +// ALIASES + +addUnitAlias('day', 'd'); +addUnitAlias('weekday', 'e'); +addUnitAlias('isoWeekday', 'E'); + +// PARSING + +addRegexToken('d', match1to2); +addRegexToken('e', match1to2); +addRegexToken('E', match1to2); +addRegexToken('dd', matchWord); +addRegexToken('ddd', matchWord); +addRegexToken('dddd', matchWord); + +addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config) { + var weekday = config._locale.weekdaysParse(input); + // if we didn't get a weekday name, mark the date as invalid + if (weekday != null) { + week.d = weekday; + } else { + getParsingFlags(config).invalidWeekday = input; + } +}); + +addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { + week[token] = toInt(input); +}); + +// HELPERS + +function parseWeekday(input, locale) { + if (typeof input === 'string') { + if (!isNaN(input)) { + input = parseInt(input, 10); + } + else { + input = locale.weekdaysParse(input); + if (typeof input !== 'number') { + return null; + } + } + } + return input; +} + +// LOCALES + +export var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'); +export function localeWeekdays (m) { + return this._weekdays[m.day()]; +} + +export var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'); +export function localeWeekdaysShort (m) { + return this._weekdaysShort[m.day()]; +} + +export var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'); +export function localeWeekdaysMin (m) { + return this._weekdaysMin[m.day()]; +} + +export function localeWeekdaysParse (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 = createLocal([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; + } + } +} + +// MOMENTS + +export function getSetDayOfWeek (input) { + var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); + if (input != null) { + input = parseWeekday(input, this.localeData()); + return this.add(input - day, 'd'); + } else { + return day; + } +} + +export function getSetLocaleDayOfWeek (input) { + var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; + return input == null ? weekday : this.add(input - weekday, 'd'); +} + +export function getSetISODayOfWeek (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); +} diff --git a/bower_components/moment/src/lib/units/day-of-year.js b/bower_components/moment/src/lib/units/day-of-year.js new file mode 100644 index 0000000..7c4d286 --- /dev/null +++ b/bower_components/moment/src/lib/units/day-of-year.js @@ -0,0 +1,49 @@ +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addRegexToken, match3, match1to3 } from '../parse/regex'; +import { daysInYear } from './year'; +import { createUTCDate } from '../create/date-from-array'; +import { addParseToken } from '../parse/token'; +import toInt from '../utils/to-int'; + +// FORMATTING + +addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); + +// ALIASES + +addUnitAlias('dayOfYear', 'DDD'); + +// PARSING + +addRegexToken('DDD', match1to3); +addRegexToken('DDDD', match3); +addParseToken(['DDD', 'DDDD'], function (input, array, config) { + config._dayOfYear = toInt(input); +}); + +// HELPERS + +//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday +export function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { + var d = createUTCDate(year, 0, 1).getUTCDay(); + var daysToAdd; + var dayOfYear; + + d = d === 0 ? 7 : d; + weekday = weekday != null ? weekday : firstDayOfWeek; + daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); + dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; + + return { + year : dayOfYear > 0 ? year : year - 1, + dayOfYear : dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear + }; +} + +// MOMENTS + +export function getSetDayOfYear (input) { + var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1; + return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); +} diff --git a/bower_components/moment/src/lib/units/hour.js b/bower_components/moment/src/lib/units/hour.js new file mode 100644 index 0000000..356c74d --- /dev/null +++ b/bower_components/moment/src/lib/units/hour.js @@ -0,0 +1,77 @@ +import { makeGetSet } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addRegexToken, match1to2, match2 } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { HOUR } from './constants'; +import toInt from '../utils/to-int'; +import getParsingFlags from '../create/parsing-flags'; + +// FORMATTING + +addFormatToken('H', ['HH', 2], 0, 'hour'); +addFormatToken('h', ['hh', 2], 0, function () { + return this.hours() % 12 || 12; +}); + +function meridiem (token, lowercase) { + addFormatToken(token, 0, 0, function () { + return this.localeData().meridiem(this.hours(), this.minutes(), lowercase); + }); +} + +meridiem('a', true); +meridiem('A', false); + +// ALIASES + +addUnitAlias('hour', 'h'); + +// PARSING + +function matchMeridiem (isStrict, locale) { + return locale._meridiemParse; +} + +addRegexToken('a', matchMeridiem); +addRegexToken('A', matchMeridiem); +addRegexToken('H', match1to2); +addRegexToken('h', match1to2); +addRegexToken('HH', match1to2, match2); +addRegexToken('hh', match1to2, match2); + +addParseToken(['H', 'HH'], HOUR); +addParseToken(['a', 'A'], function (input, array, config) { + config._isPm = config._locale.isPM(input); + config._meridiem = input; +}); +addParseToken(['h', 'hh'], function (input, array, config) { + array[HOUR] = toInt(input); + getParsingFlags(config).bigHour = true; +}); + +// LOCALES + +export function localeIsPM (input) { + // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays + // Using charAt should be more compatible. + return ((input + '').toLowerCase().charAt(0) === 'p'); +} + +export var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; +export function localeMeridiem (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'pm' : 'PM'; + } else { + return isLower ? 'am' : 'AM'; + } +} + + +// MOMENTS + +// Setting the hour should keep the time, because the user explicitly +// specified which hour he wants. So trying to maintain the same hour (in +// a new timezone) makes sense. Adding/subtracting hours does not follow +// this rule. +export var getSetHour = makeGetSet('Hours', true); diff --git a/bower_components/moment/src/lib/units/millisecond.js b/bower_components/moment/src/lib/units/millisecond.js new file mode 100644 index 0000000..2fb73af --- /dev/null +++ b/bower_components/moment/src/lib/units/millisecond.js @@ -0,0 +1,42 @@ +import { makeGetSet } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addRegexToken, match1, match2, match3, match1to3, matchUnsigned } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { MILLISECOND } from './constants'; +import toInt from '../utils/to-int'; + +// FORMATTING + +addFormatToken('S', 0, 0, function () { + return ~~(this.millisecond() / 100); +}); + +addFormatToken(0, ['SS', 2], 0, function () { + return ~~(this.millisecond() / 10); +}); + +function milliseconds (token) { + addFormatToken(0, [token, 3], 0, 'millisecond'); +} + +milliseconds('SSS'); +milliseconds('SSSS'); + +// ALIASES + +addUnitAlias('millisecond', 'ms'); + +// PARSING + +addRegexToken('S', match1to3, match1); +addRegexToken('SS', match1to3, match2); +addRegexToken('SSS', match1to3, match3); +addRegexToken('SSSS', matchUnsigned); +addParseToken(['S', 'SS', 'SSS', 'SSSS'], function (input, array) { + array[MILLISECOND] = toInt(('0.' + input) * 1000); +}); + +// MOMENTS + +export var getSetMillisecond = makeGetSet('Milliseconds', false); diff --git a/bower_components/moment/src/lib/units/minute.js b/bower_components/moment/src/lib/units/minute.js new file mode 100644 index 0000000..e9473b8 --- /dev/null +++ b/bower_components/moment/src/lib/units/minute.js @@ -0,0 +1,24 @@ +import { makeGetSet } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addRegexToken, match1to2, match2 } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { MINUTE } from './constants'; + +// FORMATTING + +addFormatToken('m', ['mm', 2], 0, 'minute'); + +// ALIASES + +addUnitAlias('minute', 'm'); + +// PARSING + +addRegexToken('m', match1to2); +addRegexToken('mm', match1to2, match2); +addParseToken(['m', 'mm'], MINUTE); + +// MOMENTS + +export var getSetMinute = makeGetSet('Minutes', false); diff --git a/bower_components/moment/src/lib/units/month.js b/bower_components/moment/src/lib/units/month.js new file mode 100644 index 0000000..63d18b4 --- /dev/null +++ b/bower_components/moment/src/lib/units/month.js @@ -0,0 +1,129 @@ +import { get } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addRegexToken, match1to2, match2, matchWord } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { hooks } from '../utils/hooks'; +import { MONTH } from './constants'; +import toInt from '../utils/to-int'; +import { createUTC } from '../create/utc'; +import getParsingFlags from '../create/parsing-flags'; + +export function daysInMonth(year, month) { + return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); +} + +// FORMATTING + +addFormatToken('M', ['MM', 2], 'Mo', function () { + return this.month() + 1; +}); + +addFormatToken('MMM', 0, 0, function (format) { + return this.localeData().monthsShort(this, format); +}); + +addFormatToken('MMMM', 0, 0, function (format) { + return this.localeData().months(this, format); +}); + +// ALIASES + +addUnitAlias('month', 'M'); + +// PARSING + +addRegexToken('M', match1to2); +addRegexToken('MM', match1to2, match2); +addRegexToken('MMM', matchWord); +addRegexToken('MMMM', matchWord); + +addParseToken(['M', 'MM'], function (input, array) { + array[MONTH] = toInt(input) - 1; +}); + +addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { + var month = config._locale.monthsParse(input, token, config._strict); + // if we didn't find a month name, mark the date as invalid. + if (month != null) { + array[MONTH] = month; + } else { + getParsingFlags(config).invalidMonth = input; + } +}); + +// LOCALES + +export var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'); +export function localeMonths (m) { + return this._months[m.month()]; +} + +export var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'); +export function localeMonthsShort (m) { + return this._monthsShort[m.month()]; +} + +export function localeMonthsParse (monthName, format, strict) { + var i, mom, regex; + + if (!this._monthsParse) { + this._monthsParse = []; + this._longMonthsParse = []; + this._shortMonthsParse = []; + } + + for (i = 0; i < 12; i++) { + // make the regex if we don't have it already + mom = createUTC([2000, i]); + if (strict && !this._longMonthsParse[i]) { + this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); + this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); + } + if (!strict && !this._monthsParse[i]) { + regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); + this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); + } + // test the regex + if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { + return i; + } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { + return i; + } else if (!strict && this._monthsParse[i].test(monthName)) { + return i; + } + } +} + +// MOMENTS + +export function setMonth (mom, value) { + var dayOfMonth; + + // TODO: Move this out of here! + if (typeof value === 'string') { + value = mom.localeData().monthsParse(value); + // TODO: Another silent failure? + if (typeof value !== 'number') { + return mom; + } + } + + dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value)); + mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); + return mom; +} + +export function getSetMonth (value) { + if (value != null) { + setMonth(this, value); + hooks.updateOffset(this, true); + return this; + } else { + return get(this, 'Month'); + } +} + +export function getDaysInMonth () { + return daysInMonth(this.year(), this.month()); +} diff --git a/bower_components/moment/src/lib/units/offset.js b/bower_components/moment/src/lib/units/offset.js new file mode 100644 index 0000000..75aeb02 --- /dev/null +++ b/bower_components/moment/src/lib/units/offset.js @@ -0,0 +1,206 @@ +import zeroFill from '../utils/zero-fill'; +import { createDuration } from '../duration/create'; +import { addSubtract } from '../moment/add-subtract'; +import { isMoment } from '../moment/constructor'; +import { addFormatToken } from '../format/format'; +import { addRegexToken, matchOffset } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { createLocal } from '../create/local'; +import { createUTC } from '../create/utc'; +import isDate from '../utils/is-date'; +import toInt from '../utils/to-int'; +import compareArrays from '../utils/compare-arrays'; +import { hooks } from '../utils/hooks'; + +// FORMATTING + +function offset (token, separator) { + addFormatToken(token, 0, 0, function () { + var offset = this.utcOffset(); + var sign = '+'; + if (offset < 0) { + offset = -offset; + sign = '-'; + } + return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2); + }); +} + +offset('Z', ':'); +offset('ZZ', ''); + +// PARSING + +addRegexToken('Z', matchOffset); +addRegexToken('ZZ', matchOffset); +addParseToken(['Z', 'ZZ'], function (input, array, config) { + config._useUTC = true; + config._tzm = offsetFromString(input); +}); + +// HELPERS + +// timezone chunker +// '+10:00' > ['10', '00'] +// '-1530' > ['-15', '30'] +var chunkOffset = /([\+\-]|\d\d)/gi; + +function offsetFromString(string) { + var matches = ((string || '').match(matchOffset) || []); + var chunk = matches[matches.length - 1] || []; + var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0]; + var minutes = +(parts[1] * 60) + toInt(parts[2]); + + return parts[0] === '+' ? minutes : -minutes; +} + +// Return a moment from input, that is local/utc/zone equivalent to model. +export function cloneWithOffset(input, model) { + var res, diff; + if (model._isUTC) { + res = model.clone(); + diff = (isMoment(input) || isDate(input) ? +input : +createLocal(input)) - (+res); + // Use low-level api, because this fn is low-level api. + res._d.setTime(+res._d + diff); + hooks.updateOffset(res, false); + return res; + } else { + return createLocal(input).local(); + } + return model._isUTC ? createLocal(input).zone(model._offset || 0) : createLocal(input).local(); +} + +function getDateOffset (m) { + // On Firefox.24 Date#getTimezoneOffset returns a floating point. + // https://github.com/moment/moment/pull/1871 + return -Math.round(m._d.getTimezoneOffset() / 15) * 15; +} + +// HOOKS + +// This function will be called whenever a moment is mutated. +// It is intended to keep the offset in sync with the timezone. +hooks.updateOffset = function () {}; + +// MOMENTS + +// keepLocalTime = true means only change the timezone, without +// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> +// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset +// +0200, so we adjust the time as needed, to be valid. +// +// Keeping the time actually adds/subtracts (one hour) +// from the actual represented time. That is why we call updateOffset +// a second time. In case it wants us to change the offset again +// _changeInProgress == true case, then we have to adjust, because +// there is no such time in the given timezone. +export function getSetOffset (input, keepLocalTime) { + var offset = this._offset || 0, + localAdjust; + if (input != null) { + if (typeof input === 'string') { + input = offsetFromString(input); + } + if (Math.abs(input) < 16) { + input = input * 60; + } + if (!this._isUTC && keepLocalTime) { + localAdjust = getDateOffset(this); + } + this._offset = input; + this._isUTC = true; + if (localAdjust != null) { + this.add(localAdjust, 'm'); + } + if (offset !== input) { + if (!keepLocalTime || this._changeInProgress) { + addSubtract(this, createDuration(input - offset, 'm'), 1, false); + } else if (!this._changeInProgress) { + this._changeInProgress = true; + hooks.updateOffset(this, true); + this._changeInProgress = null; + } + } + return this; + } else { + return this._isUTC ? offset : getDateOffset(this); + } +} + +export function getSetZone (input, keepLocalTime) { + if (input != null) { + if (typeof input !== 'string') { + input = -input; + } + + this.utcOffset(input, keepLocalTime); + + return this; + } else { + return -this.utcOffset(); + } +} + +export function setOffsetToUTC (keepLocalTime) { + return this.utcOffset(0, keepLocalTime); +} + +export function setOffsetToLocal (keepLocalTime) { + if (this._isUTC) { + this.utcOffset(0, keepLocalTime); + this._isUTC = false; + + if (keepLocalTime) { + this.subtract(getDateOffset(this), 'm'); + } + } + return this; +} + +export function setOffsetToParsedOffset () { + if (this._tzm) { + this.utcOffset(this._tzm); + } else if (typeof this._i === 'string') { + this.utcOffset(offsetFromString(this._i)); + } + return this; +} + +export function hasAlignedHourOffset (input) { + if (!input) { + input = 0; + } + else { + input = createLocal(input).utcOffset(); + } + + return (this.utcOffset() - input) % 60 === 0; +} + +export function isDaylightSavingTime () { + return ( + this.utcOffset() > this.clone().month(0).utcOffset() || + this.utcOffset() > this.clone().month(5).utcOffset() + ); +} + +export function isDaylightSavingTimeShifted () { + if (this._a) { + var other = this._isUTC ? createUTC(this._a) : createLocal(this._a); + return this.isValid() && compareArrays(this._a, other.toArray()) > 0; + } + + return false; +} + +export function isLocal () { + return !this._isUTC; +} + +export function isUtcOffset () { + return this._isUTC; +} + +export function isUtc () { + return this._isUTC && this._offset === 0; +} diff --git a/bower_components/moment/src/lib/units/quarter.js b/bower_components/moment/src/lib/units/quarter.js new file mode 100644 index 0000000..d383f56 --- /dev/null +++ b/bower_components/moment/src/lib/units/quarter.js @@ -0,0 +1,27 @@ +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addRegexToken, match1 } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { MONTH } from './constants'; +import toInt from '../utils/to-int'; + +// FORMATTING + +addFormatToken('Q', 0, 0, 'quarter'); + +// ALIASES + +addUnitAlias('quarter', 'Q'); + +// PARSING + +addRegexToken('Q', match1); +addParseToken('Q', function (input, array) { + array[MONTH] = (toInt(input) - 1) * 3; +}); + +// MOMENTS + +export function getSetQuarter (input) { + return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); +} diff --git a/bower_components/moment/src/lib/units/second.js b/bower_components/moment/src/lib/units/second.js new file mode 100644 index 0000000..118fe30 --- /dev/null +++ b/bower_components/moment/src/lib/units/second.js @@ -0,0 +1,24 @@ +import { makeGetSet } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addRegexToken, match1to2, match2 } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { SECOND } from './constants'; + +// FORMATTING + +addFormatToken('s', ['ss', 2], 0, 'second'); + +// ALIASES + +addUnitAlias('second', 's'); + +// PARSING + +addRegexToken('s', match1to2); +addRegexToken('ss', match1to2, match2); +addParseToken(['s', 'ss'], SECOND); + +// MOMENTS + +export var getSetSecond = makeGetSet('Seconds', false); diff --git a/bower_components/moment/src/lib/units/timestamp.js b/bower_components/moment/src/lib/units/timestamp.js new file mode 100644 index 0000000..a49e1e4 --- /dev/null +++ b/bower_components/moment/src/lib/units/timestamp.js @@ -0,0 +1,20 @@ +import { addFormatToken } from '../format/format'; +import { addRegexToken, matchTimestamp, matchSigned } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import toInt from '../utils/to-int'; + +// FORMATTING + +addFormatToken('X', 0, 0, 'unix'); +addFormatToken('x', 0, 0, 'valueOf'); + +// PARSING + +addRegexToken('x', matchSigned); +addRegexToken('X', matchTimestamp); +addParseToken('X', function (input, array, config) { + config._d = new Date(parseFloat(input, 10) * 1000); +}); +addParseToken('x', function (input, array, config) { + config._d = new Date(toInt(input)); +}); diff --git a/bower_components/moment/src/lib/units/timezone.js b/bower_components/moment/src/lib/units/timezone.js new file mode 100644 index 0000000..20c81cd --- /dev/null +++ b/bower_components/moment/src/lib/units/timezone.js @@ -0,0 +1,16 @@ +import { addFormatToken } from '../format/format'; + +// FORMATTING + +addFormatToken('z', 0, 0, 'zoneAbbr'); +addFormatToken('zz', 0, 0, 'zoneName'); + +// MOMENTS + +export function getZoneAbbr () { + return this._isUTC ? 'UTC' : ''; +} + +export function getZoneName () { + return this._isUTC ? 'Coordinated Universal Time' : ''; +} diff --git a/bower_components/moment/src/lib/units/units.js b/bower_components/moment/src/lib/units/units.js new file mode 100644 index 0000000..6f45f1c --- /dev/null +++ b/bower_components/moment/src/lib/units/units.js @@ -0,0 +1,20 @@ +// Side effect imports +import './day-of-month'; +import './day-of-week'; +import './day-of-year'; +import './hour'; +import './millisecond'; +import './minute'; +import './month'; +import './offset'; +import './quarter'; +import './second'; +import './timestamp'; +import './timezone'; +import './week-year'; +import './week'; +import './year'; + +import { normalizeUnits } from './aliases'; + +export { normalizeUnits }; diff --git a/bower_components/moment/src/lib/units/week-year.js b/bower_components/moment/src/lib/units/week-year.js new file mode 100644 index 0000000..8ecfce7 --- /dev/null +++ b/bower_components/moment/src/lib/units/week-year.js @@ -0,0 +1,78 @@ +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addRegexToken, match1to2, match1to4, match1to6, match2, match4, match6, matchSigned } from '../parse/regex'; +import { addWeekParseToken } from '../parse/token'; +import { weekOfYear } from './week'; +import toInt from '../utils/to-int'; +import { hooks } from '../utils/hooks'; +import { createLocal } from '../create/local'; + +// FORMATTING + +addFormatToken(0, ['gg', 2], 0, function () { + return this.weekYear() % 100; +}); + +addFormatToken(0, ['GG', 2], 0, function () { + return this.isoWeekYear() % 100; +}); + +function addWeekYearFormatToken (token, getter) { + addFormatToken(0, [token, token.length], 0, getter); +} + +addWeekYearFormatToken('gggg', 'weekYear'); +addWeekYearFormatToken('ggggg', 'weekYear'); +addWeekYearFormatToken('GGGG', 'isoWeekYear'); +addWeekYearFormatToken('GGGGG', 'isoWeekYear'); + +// ALIASES + +addUnitAlias('weekYear', 'gg'); +addUnitAlias('isoWeekYear', 'GG'); + +// PARSING + +addRegexToken('G', matchSigned); +addRegexToken('g', matchSigned); +addRegexToken('GG', match1to2, match2); +addRegexToken('gg', match1to2, match2); +addRegexToken('GGGG', match1to4, match4); +addRegexToken('gggg', match1to4, match4); +addRegexToken('GGGGG', match1to6, match6); +addRegexToken('ggggg', match1to6, match6); + +addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) { + week[token.substr(0, 2)] = toInt(input); +}); + +addWeekParseToken(['gg', 'GG'], function (input, week, config, token) { + week[token] = hooks.parseTwoDigitYear(input); +}); + +// HELPERS + +function weeksInYear(year, dow, doy) { + return weekOfYear(createLocal([year, 11, 31 + dow - doy]), dow, doy).week; +} + +// MOMENTS + +export function getSetWeekYear (input) { + var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year; + return input == null ? year : this.add((input - year), 'y'); +} + +export function getSetISOWeekYear (input) { + var year = weekOfYear(this, 1, 4).year; + return input == null ? year : this.add((input - year), 'y'); +} + +export function getISOWeeksInYear () { + return weeksInYear(this.year(), 1, 4); +} + +export function getWeeksInYear () { + var weekInfo = this.localeData()._week; + return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); +} diff --git a/bower_components/moment/src/lib/units/week.js b/bower_components/moment/src/lib/units/week.js new file mode 100644 index 0000000..178f6b5 --- /dev/null +++ b/bower_components/moment/src/lib/units/week.js @@ -0,0 +1,88 @@ +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addRegexToken, match1to2, match2 } from '../parse/regex'; +import { addWeekParseToken } from '../parse/token'; +import toInt from '../utils/to-int'; +import { createLocal } from '../create/local'; + +// FORMATTING + +addFormatToken('w', ['ww', 2], 'wo', 'week'); +addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); + +// ALIASES + +addUnitAlias('week', 'w'); +addUnitAlias('isoWeek', 'W'); + +// PARSING + +addRegexToken('w', match1to2); +addRegexToken('ww', match1to2, match2); +addRegexToken('W', match1to2); +addRegexToken('WW', match1to2, match2); + +addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { + week[token.substr(0, 1)] = toInt(input); +}); + +// HELPERS + +// 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)) +export 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 = createLocal(mom).add(daysToDayOfWeek, 'd'); + return { + week: Math.ceil(adjustedMoment.dayOfYear() / 7), + year: adjustedMoment.year() + }; +} + +// LOCALES + +export function localeWeek (mom) { + return weekOfYear(mom, this._week.dow, this._week.doy).week; +} + +export var defaultLocaleWeek = { + 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. +}; + +export function localeFirstDayOfWeek () { + return this._week.dow; +} + +export function localeFirstDayOfYear () { + return this._week.doy; +} + +// MOMENTS + +export function getSetWeek (input) { + var week = this.localeData().week(this); + return input == null ? week : this.add((input - week) * 7, 'd'); +} + +export function getSetISOWeek (input) { + var week = weekOfYear(this, 1, 4).week; + return input == null ? week : this.add((input - week) * 7, 'd'); +} diff --git a/bower_components/moment/src/lib/units/year.js b/bower_components/moment/src/lib/units/year.js new file mode 100644 index 0000000..4d8a03b --- /dev/null +++ b/bower_components/moment/src/lib/units/year.js @@ -0,0 +1,60 @@ +import { makeGetSet } from '../moment/get-set'; +import { addFormatToken } from '../format/format'; +import { addUnitAlias } from './aliases'; +import { addRegexToken, match1to2, match1to4, match1to6, match2, match4, match6, matchSigned } from '../parse/regex'; +import { addParseToken } from '../parse/token'; +import { hooks } from '../utils/hooks'; +import { YEAR } from './constants'; +import toInt from '../utils/to-int'; + +// FORMATTING + +addFormatToken(0, ['YY', 2], 0, function () { + return this.year() % 100; +}); + +addFormatToken(0, ['YYYY', 4], 0, 'year'); +addFormatToken(0, ['YYYYY', 5], 0, 'year'); +addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); + +// ALIASES + +addUnitAlias('year', 'y'); + +// PARSING + +addRegexToken('Y', matchSigned); +addRegexToken('YY', match1to2, match2); +addRegexToken('YYYY', match1to4, match4); +addRegexToken('YYYYY', match1to6, match6); +addRegexToken('YYYYYY', match1to6, match6); + +addParseToken(['YYYY', 'YYYYY', 'YYYYYY'], YEAR); +addParseToken('YY', function (input, array) { + array[YEAR] = hooks.parseTwoDigitYear(input); +}); + +// HELPERS + +export function daysInYear(year) { + return isLeapYear(year) ? 366 : 365; +} + +function isLeapYear(year) { + return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; +} + +// HOOKS + +hooks.parseTwoDigitYear = function (input) { + return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); +}; + +// MOMENTS + +export var getSetYear = makeGetSet('FullYear', false); + +export function getIsLeapYear () { + return isLeapYear(this.year()); +} + diff --git a/bower_components/moment/src/lib/utils/abs-floor.js b/bower_components/moment/src/lib/utils/abs-floor.js new file mode 100644 index 0000000..8ba1318 --- /dev/null +++ b/bower_components/moment/src/lib/utils/abs-floor.js @@ -0,0 +1,7 @@ +export default function absFloor (number) { + if (number < 0) { + return Math.ceil(number); + } else { + return Math.floor(number); + } +} diff --git a/bower_components/moment/src/lib/utils/compare-arrays.js b/bower_components/moment/src/lib/utils/compare-arrays.js new file mode 100644 index 0000000..2eb274b --- /dev/null +++ b/bower_components/moment/src/lib/utils/compare-arrays.js @@ -0,0 +1,16 @@ +import toInt from './to-int'; + +// compare two arrays, return the number of differences +export default function compareArrays(array1, array2, dontConvert) { + 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 ((dontConvert && array1[i] !== array2[i]) || + (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { + diffs++; + } + } + return diffs + lengthDiff; +} diff --git a/bower_components/moment/src/lib/utils/defaults.js b/bower_components/moment/src/lib/utils/defaults.js new file mode 100644 index 0000000..45c5e87 --- /dev/null +++ b/bower_components/moment/src/lib/utils/defaults.js @@ -0,0 +1,10 @@ +// Pick the first defined of two or three arguments. +export default function defaults(a, b, c) { + if (a != null) { + return a; + } + if (b != null) { + return b; + } + return c; +} diff --git a/bower_components/moment/src/lib/utils/deprecate.js b/bower_components/moment/src/lib/utils/deprecate.js new file mode 100644 index 0000000..a076ad7 --- /dev/null +++ b/bower_components/moment/src/lib/utils/deprecate.js @@ -0,0 +1,33 @@ +import extend from './extend'; +import { hooks } from './hooks'; + +function warn(msg) { + if (hooks.suppressDeprecationWarnings === false && typeof console !== 'undefined' && console.warn) { + console.warn('Deprecation warning: ' + msg); + } +} + +export function deprecate(msg, fn) { + var firstTime = true, + msgWithStack = msg + '\n' + (new Error()).stack; + + return extend(function () { + if (firstTime) { + warn(msgWithStack); + firstTime = false; + } + return fn.apply(this, arguments); + }, fn); +} + +var deprecations = {}; + +export function deprecateSimple(name, msg) { + if (!deprecations[name]) { + warn(msg); + deprecations[name] = true; + } +} + +hooks.suppressDeprecationWarnings = false; + diff --git a/bower_components/moment/src/lib/utils/extend.js b/bower_components/moment/src/lib/utils/extend.js new file mode 100644 index 0000000..ba74a0b --- /dev/null +++ b/bower_components/moment/src/lib/utils/extend.js @@ -0,0 +1,19 @@ +import hasOwnProp from './has-own-prop'; + +export default function extend(a, b) { + for (var i in b) { + if (hasOwnProp(b, i)) { + a[i] = b[i]; + } + } + + if (hasOwnProp(b, 'toString')) { + a.toString = b.toString; + } + + if (hasOwnProp(b, 'valueOf')) { + a.valueOf = b.valueOf; + } + + return a; +} diff --git a/bower_components/moment/src/lib/utils/has-own-prop.js b/bower_components/moment/src/lib/utils/has-own-prop.js new file mode 100644 index 0000000..4d2403c --- /dev/null +++ b/bower_components/moment/src/lib/utils/has-own-prop.js @@ -0,0 +1,3 @@ +export default function hasOwnProp(a, b) { + return Object.prototype.hasOwnProperty.call(a, b); +} diff --git a/bower_components/moment/src/lib/utils/hooks.js b/bower_components/moment/src/lib/utils/hooks.js new file mode 100644 index 0000000..02a5bd3 --- /dev/null +++ b/bower_components/moment/src/lib/utils/hooks.js @@ -0,0 +1,13 @@ +export { hooks, setHookCallback }; + +var hookCallback; + +function hooks () { + return hookCallback.apply(null, arguments); +} + +// This is done to register the method called with moment() +// without creating circular dependencies. +function setHookCallback (callback) { + hookCallback = callback; +} diff --git a/bower_components/moment/src/lib/utils/is-array.js b/bower_components/moment/src/lib/utils/is-array.js new file mode 100644 index 0000000..46bd6c6 --- /dev/null +++ b/bower_components/moment/src/lib/utils/is-array.js @@ -0,0 +1,3 @@ +export default function isArray(input) { + return Object.prototype.toString.call(input) === '[object Array]'; +} diff --git a/bower_components/moment/src/lib/utils/is-date.js b/bower_components/moment/src/lib/utils/is-date.js new file mode 100644 index 0000000..69c4d0e --- /dev/null +++ b/bower_components/moment/src/lib/utils/is-date.js @@ -0,0 +1,3 @@ +export default function isDate(input) { + return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]'; +} diff --git a/bower_components/moment/src/lib/utils/map.js b/bower_components/moment/src/lib/utils/map.js new file mode 100644 index 0000000..1cbc563 --- /dev/null +++ b/bower_components/moment/src/lib/utils/map.js @@ -0,0 +1,7 @@ +export default function map(arr, fn) { + var res = [], i; + for (i = 0; i < arr.length; ++i) { + res.push(fn(arr[i], i)); + } + return res; +} diff --git a/bower_components/moment/src/lib/utils/to-int.js b/bower_components/moment/src/lib/utils/to-int.js new file mode 100644 index 0000000..945e019 --- /dev/null +++ b/bower_components/moment/src/lib/utils/to-int.js @@ -0,0 +1,14 @@ +export default function toInt(argumentForCoercion) { + var coercedNumber = +argumentForCoercion, + value = 0; + + if (coercedNumber !== 0 && isFinite(coercedNumber)) { + if (coercedNumber >= 0) { + value = Math.floor(coercedNumber); + } else { + value = Math.ceil(coercedNumber); + } + } + + return value; +} diff --git a/bower_components/moment/src/lib/utils/zero-fill.js b/bower_components/moment/src/lib/utils/zero-fill.js new file mode 100644 index 0000000..af45dd9 --- /dev/null +++ b/bower_components/moment/src/lib/utils/zero-fill.js @@ -0,0 +1,9 @@ +export default function zeroFill(number, targetLength, forceSign) { + var output = '' + Math.abs(number), + sign = number >= 0; + + while (output.length < targetLength) { + output = '0' + output; + } + return (sign ? (forceSign ? '+' : '') : '-') + output; +} diff --git a/bower_components/moment/src/locale/af.js b/bower_components/moment/src/locale/af.js new file mode 100644 index 0000000..8a490ef --- /dev/null +++ b/bower_components/moment/src/locale/af.js @@ -0,0 +1,63 @@ +//! moment.js locale configuration +//! locale : afrikaans (af) +//! author : Werner Mollentze : https://github.com/wernerm + +import moment from '../moment'; + +export default moment.defineLocale('af', { + months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'), + weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'), + weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'), + weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'), + meridiemParse: /vm|nm/i, + isPM : function (input) { + return /^nm$/i.test(input); + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower ? 'vm' : 'VM'; + } else { + return isLower ? 'nm' : 'NM'; + } + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd, D MMMM YYYY LT' + }, + calendar : { + sameDay : '[Vandag om] LT', + nextDay : '[Môre om] LT', + nextWeek : 'dddd [om] LT', + lastDay : '[Gister om] LT', + lastWeek : '[Laas] dddd [om] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'oor %s', + past : '%s gelede', + s : '\'n paar sekondes', + m : '\'n minuut', + mm : '%d minute', + h : '\'n uur', + hh : '%d ure', + d : '\'n dag', + dd : '%d dae', + M : '\'n maand', + MM : '%d maande', + y : '\'n jaar', + yy : '%d jaar' + }, + ordinalParse: /\d{1,2}(ste|de)/, + ordinal : function (number) { + return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter + }, + week : { + dow : 1, // Maandag is die eerste dag van die week. + doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar. + } +}); diff --git a/bower_components/moment/src/locale/ar-ma.js b/bower_components/moment/src/locale/ar-ma.js new file mode 100644 index 0000000..374468e --- /dev/null +++ b/bower_components/moment/src/locale/ar-ma.js @@ -0,0 +1,50 @@ +//! moment.js locale configuration +//! locale : Moroccan Arabic (ar-ma) +//! author : ElFadili Yassine : https://github.com/ElFadiliY +//! author : Abdel Said : https://github.com/abdelsaid + +import moment from '../moment'; + +export default moment.defineLocale('ar-ma', { + months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'), + weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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/bower_components/moment/src/locale/ar-sa.js b/bower_components/moment/src/locale/ar-sa.js new file mode 100644 index 0000000..a0ef282 --- /dev/null +++ b/bower_components/moment/src/locale/ar-sa.js @@ -0,0 +1,94 @@ +//! moment.js locale configuration +//! locale : Arabic Saudi Arabia (ar-sa) +//! author : Suhail Alkowaileet : https://github.com/xsoh + +import moment from '../moment'; + +var symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' +}, numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' +}; + +export default moment.defineLocale('ar-sa', { + months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D MMMM YYYY LT' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + 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, '،'); + }, + 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/bower_components/moment/src/locale/ar-tn.js b/bower_components/moment/src/locale/ar-tn.js new file mode 100644 index 0000000..acb3e08 --- /dev/null +++ b/bower_components/moment/src/locale/ar-tn.js @@ -0,0 +1,48 @@ +//! moment.js locale configuration +//! locale : Tunisian Arabic (ar-tn) + +import moment from '../moment'; + +export default moment.defineLocale('ar-tn', { + months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'), + weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat: { + LT: 'HH:mm', + LTS: 'LT:ss', + 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: 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/bower_components/moment/src/locale/ar.js b/bower_components/moment/src/locale/ar.js new file mode 100644 index 0000000..689bc8f --- /dev/null +++ b/bower_components/moment/src/locale/ar.js @@ -0,0 +1,127 @@ +//! moment.js locale configuration +//! Locale: Arabic (ar) +//! Author: Abdel Said: https://github.com/abdelsaid +//! Changes in months, weekdays: Ahmed Elkhatib +//! Native plural forms: forabi https://github.com/forabi + +import moment from '../moment'; + +var symbolMap = { + '1': '١', + '2': '٢', + '3': '٣', + '4': '٤', + '5': '٥', + '6': '٦', + '7': '٧', + '8': '٨', + '9': '٩', + '0': '٠' +}, numberMap = { + '١': '1', + '٢': '2', + '٣': '3', + '٤': '4', + '٥': '5', + '٦': '6', + '٧': '7', + '٨': '8', + '٩': '9', + '٠': '0' +}, pluralForm = function (n) { + return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5; +}, plurals = { + s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'], + m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'], + h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'], + d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'], + M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'], + y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام'] +}, pluralize = function (u) { + return function (number, withoutSuffix, string, isFuture) { + var f = pluralForm(number), + str = plurals[u][pluralForm(number)]; + if (f === 2) { + str = str[withoutSuffix ? 0 : 1]; + } + return str.replace(/%d/i, number); + }; +}, months = [ + 'كانون الثاني يناير', + 'شباط فبراير', + 'آذار مارس', + 'نيسان أبريل', + 'أيار مايو', + 'حزيران يونيو', + 'تموز يوليو', + 'آب أغسطس', + 'أيلول سبتمبر', + 'تشرين الأول أكتوبر', + 'تشرين الثاني نوفمبر', + 'كانون الأول ديسمبر' +]; + +export default moment.defineLocale('ar', { + months : months, + monthsShort : months, + weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'), + weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'), + weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'HH:mm:ss', + L : 'D/\u200FM/\u200FYYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D MMMM YYYY LT' + }, + meridiemParse: /ص|م/, + isPM : function (input) { + return 'م' === input; + }, + 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 : pluralize('s'), + m : pluralize('m'), + mm : pluralize('m'), + h : pluralize('h'), + hh : pluralize('h'), + d : pluralize('d'), + dd : pluralize('d'), + M : pluralize('M'), + MM : pluralize('M'), + y : pluralize('y'), + yy : pluralize('y') + }, + preparse: function (string) { + return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) { + return numberMap[match]; + }).replace(/،/g, ','); + }, + postformat: function (string) { + return string.replace(/\d/g, function (match) { + return symbolMap[match]; + }).replace(/,/g, '،'); + }, + 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/bower_components/moment/src/locale/az.js b/bower_components/moment/src/locale/az.js new file mode 100644 index 0000000..ecf9352 --- /dev/null +++ b/bower_components/moment/src/locale/az.js @@ -0,0 +1,95 @@ +//! moment.js locale configuration +//! locale : azerbaijani (az) +//! author : topchiyev : https://github.com/topchiyev + +import moment from '../moment'; + +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ı' +}; + +export default moment.defineLocale('az', { + months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'), + monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'), + weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'), + weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'), + weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : '[sabah saat] LT', + nextWeek : '[gələn həftə] dddd [saat] LT', + lastDay : '[dünən] LT', + lastWeek : '[keçən həftə] dddd [saat] LT', + sameElse : 'L' + }, + relativeTime : { + future : '%s sonra', + past : '%s əvvəl', + s : 'birneçə saniyyə', + m : 'bir dəqiqə', + mm : '%d dəqiqə', + h : 'bir saat', + hh : '%d saat', + d : 'bir gün', + dd : '%d gün', + M : 'bir ay', + MM : '%d ay', + y : 'bir il', + yy : '%d il' + }, + meridiemParse: /gecə|səhər|gündüz|axşam/, + isPM : function (input) { + return /^(gündüz|axşam)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'gecə'; + } else if (hour < 12) { + return 'səhər'; + } else if (hour < 17) { + return 'gündüz'; + } else { + return 'axşam'; + } + }, + ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/, + 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/bower_components/moment/src/locale/be.js b/bower_components/moment/src/locale/be.js new file mode 100644 index 0000000..c145116 --- /dev/null +++ b/bower_components/moment/src/locale/be.js @@ -0,0 +1,138 @@ +//! moment.js locale configuration +//! locale : belarusian (be) +//! author : Dmitry Demidov : https://github.com/demidov91 +//! author: Praleska: http://praleska.pro/ +//! Author : Menelion Elensúle : https://github.com/Oire + +import moment from '../moment'; + +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': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін', + 'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін', + '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]?(\[[^\[\]]*\]|\s+)+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()]; +} + +export default moment.defineLocale('be', { + months : monthsCaseReplace, + monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'), + weekdays : weekdaysCaseReplace, + weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 '[У] dddd [ў] LT'; + }, + lastWeek: function () { + switch (this.day()) { + case 0: + case 3: + case 5: + case 6: + return '[У мінулую] dddd [ў] LT'; + case 1: + case 2: + case 4: + return '[У мінулы] dddd [ў] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : 'праз %s', + past : '%s таму', + s : 'некалькі секунд', + m : relativeTimeWithPlural, + mm : relativeTimeWithPlural, + h : relativeTimeWithPlural, + hh : relativeTimeWithPlural, + d : 'дзень', + dd : relativeTimeWithPlural, + M : 'месяц', + MM : relativeTimeWithPlural, + y : 'год', + yy : relativeTimeWithPlural + }, + meridiemParse: /ночы|раніцы|дня|вечара/, + isPM : function (input) { + return /^(дня|вечара)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночы'; + } else if (hour < 12) { + return 'раніцы'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечара'; + } + }, + ordinalParse: /\d{1,2}-(і|ы|га)/, + ordinal: function (number, period) { + switch (period) { + case 'M': + case 'd': + case 'DDD': + case 'w': + case 'W': + return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : 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/bower_components/moment/src/locale/bg.js b/bower_components/moment/src/locale/bg.js new file mode 100644 index 0000000..a1f1f72 --- /dev/null +++ b/bower_components/moment/src/locale/bg.js @@ -0,0 +1,81 @@ +//! moment.js locale configuration +//! locale : bulgarian (bg) +//! author : Krasen Borisov : https://github.com/kraz + +import moment from '../moment'; + +export default moment.defineLocale('bg', { + months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'), + weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + 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 години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + 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/bower_components/moment/src/locale/bn.js b/bower_components/moment/src/locale/bn.js new file mode 100644 index 0000000..3a16085 --- /dev/null +++ b/bower_components/moment/src/locale/bn.js @@ -0,0 +1,104 @@ +//! moment.js locale configuration +//! locale : Bengali (bn) +//! author : Kaushik Gandhi : https://github.com/kaushikgandhi + +import moment from '../moment'; + +var symbolMap = { + '1': '১', + '2': '২', + '3': '৩', + '4': '৪', + '5': '৫', + '6': '৬', + '7': '৭', + '8': '৮', + '9': '৯', + '0': '০' +}, +numberMap = { + '১': '1', + '২': '2', + '৩': '3', + '৪': '4', + '৫': '5', + '৬': '6', + '৭': '7', + '৮': '8', + '৯': '9', + '০': '0' +}; + +export default moment.defineLocale('bn', { + months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'), + monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split('_'), + weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রুবার_শনিবার'.split('_'), + weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্রু_শনি'.split('_'), + weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'), + longDateFormat : { + LT : 'A h:mm সময়', + LTS : 'A h:mm:ss সময়', + 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]; + }); + }, + meridiemParse: /রাত|শকাল|দুপুর|বিকেল|রাত/, + isPM: function (input) { + return /^(দুপুর|বিকেল|রাত)$/.test(input); + }, + //Bengali is a vast language its spoken + //in different forms in various parts of the world. + //I have just generalized with most common one used + 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/bower_components/moment/src/locale/bo.js b/bower_components/moment/src/locale/bo.js new file mode 100644 index 0000000..102bf3a --- /dev/null +++ b/bower_components/moment/src/locale/bo.js @@ -0,0 +1,101 @@ +//! moment.js locale configuration +//! locale : tibetan (bo) +//! author : Thupten N. Chakrishar : https://github.com/vajradog + +import moment from '../moment'; + +var symbolMap = { + '1': '༡', + '2': '༢', + '3': '༣', + '4': '༤', + '5': '༥', + '6': '༦', + '7': '༧', + '8': '༨', + '9': '༩', + '0': '༠' +}, +numberMap = { + '༡': '1', + '༢': '2', + '༣': '3', + '༤': '4', + '༥': '5', + '༦': '6', + '༧': '7', + '༨': '8', + '༩': '9', + '༠': '0' +}; + +export default moment.defineLocale('bo', { + months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'), + weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'), + weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'), + longDateFormat : { + LT : 'A h:mm', + LTS : 'LT:ss', + 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 : '[བདུན་ཕྲག་རྗེས་མ], 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]; + }); + }, + meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/, + isPM: function (input) { + return /^(ཉིན་གུང|དགོང་དག|མཚན་མོ)$/.test(input); + }, + 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/bower_components/moment/src/locale/br.js b/bower_components/moment/src/locale/br.js new file mode 100644 index 0000000..d6b501d --- /dev/null +++ b/bower_components/moment/src/locale/br.js @@ -0,0 +1,98 @@ +//! moment.js locale configuration +//! locale : breton (br) +//! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou + +import moment from '../moment'; + +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); +} + +export default moment.defineLocale('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', + LTS : 'h[e]mm:ss 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 + }, + ordinalParse: /\d{1,2}(añ|vet)/, + 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/bower_components/moment/src/locale/bs.js b/bower_components/moment/src/locale/bs.js new file mode 100644 index 0000000..62b7f8e --- /dev/null +++ b/bower_components/moment/src/locale/bs.js @@ -0,0 +1,132 @@ +//! moment.js locale configuration +//! locale : bosnian (bs) +//! author : Nedim Cholich : https://github.com/frontyard +//! based on (hr) translation by Bojan Marković + +import moment from '../moment'; + +function translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } +} + +export default moment.defineLocale('bs', { + months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'), + monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'), + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : translate, + mm : translate, + h : translate, + hh : translate, + d : 'dan', + dd : translate, + M : 'mjesec', + MM : translate, + y : 'godinu', + yy : translate + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/ca.js b/bower_components/moment/src/locale/ca.js new file mode 100644 index 0000000..f03f450 --- /dev/null +++ b/bower_components/moment/src/locale/ca.js @@ -0,0 +1,70 @@ +//! moment.js locale configuration +//! locale : catalan (ca) +//! author : Juan G. Hurtado : https://github.com/juanghurtado + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(r|n|t|è|a)/, + ordinal : function (number, period) { + var output = (number === 1) ? 'r' : + (number === 2) ? 'n' : + (number === 3) ? 'r' : + (number === 4) ? 't' : 'è'; + if (period === 'w' || period === 'W') { + output = 'a'; + } + 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/bower_components/moment/src/locale/cs.js b/bower_components/moment/src/locale/cs.js new file mode 100644 index 0000000..9388ee8 --- /dev/null +++ b/bower_components/moment/src/locale/cs.js @@ -0,0 +1,148 @@ +//! moment.js locale configuration +//! locale : czech (cs) +//! author : petrbela : https://github.com/petrbela + +import moment from '../moment'; + +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 sekund' : 'pár sekundami'; + 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; + } +} + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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 + }, + ordinalParse : /\d{1,2}\./, + 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/bower_components/moment/src/locale/cv.js b/bower_components/moment/src/locale/cv.js new file mode 100644 index 0000000..09db067 --- /dev/null +++ b/bower_components/moment/src/locale/cv.js @@ -0,0 +1,53 @@ +//! moment.js locale configuration +//! locale : chuvash (cv) +//! author : Anatoly Mironov : https://github.com/mirontoli + +import moment from '../moment'; + +export default moment.defineLocale('cv', { + months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'), + monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'), + weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'), + weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'), + weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 ҫул' + }, + ordinalParse: /\d{1,2}-мӗш/, + 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/bower_components/moment/src/locale/cy.js b/bower_components/moment/src/locale/cy.js new file mode 100644 index 0000000..2d574a6 --- /dev/null +++ b/bower_components/moment/src/locale/cy.js @@ -0,0 +1,70 @@ +//! moment.js locale configuration +//! locale : Welsh (cy) +//! author : Robert Allen + +import moment from '../moment'; + +export default moment.defineLocale('cy', { + months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'), + monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'), + weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'), + weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'), + weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'), + // time formats are the same as en-gb + longDateFormat: { + LT: 'HH:mm', + LTS : 'LT:ss', + L: 'DD/MM/YYYY', + LL: 'D MMMM YYYY', + LLL: 'D MMMM YYYY LT', + LLLL: 'dddd, D MMMM YYYY LT' + }, + calendar: { + sameDay: '[Heddiw am] LT', + nextDay: '[Yfory am] LT', + nextWeek: 'dddd [am] LT', + lastDay: '[Ddoe am] LT', + lastWeek: 'dddd [diwethaf am] LT', + sameElse: 'L' + }, + relativeTime: { + future: 'mewn %s', + past: '%s yn ôl', + s: 'ychydig eiliadau', + m: 'munud', + mm: '%d munud', + h: 'awr', + hh: '%d awr', + d: 'diwrnod', + dd: '%d diwrnod', + M: 'mis', + MM: '%d mis', + y: 'blwyddyn', + yy: '%d flynedd' + }, + ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/, + // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh + ordinal: function (number) { + var b = number, + output = '', + lookup = [ + '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed + 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed + ]; + if (b > 20) { + if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) { + output = 'fed'; // not 30ain, 70ain or 90ain + } else { + output = 'ain'; + } + } else if (b > 0) { + output = lookup[b]; + } + 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/bower_components/moment/src/locale/da.js b/bower_components/moment/src/locale/da.js new file mode 100644 index 0000000..9ee0113 --- /dev/null +++ b/bower_components/moment/src/locale/da.js @@ -0,0 +1,51 @@ +//! moment.js locale configuration +//! locale : danish (da) +//! author : Ulrik Nielsen : https://github.com/mrbase + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd [d.] 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' + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/de-at.js b/bower_components/moment/src/locale/de-at.js new file mode 100644 index 0000000..4aae191 --- /dev/null +++ b/bower_components/moment/src/locale/de-at.js @@ -0,0 +1,67 @@ +//! moment.js locale configuration +//! locale : austrian german (de-at) +//! author : lluchs : https://github.com/lluchs +//! author: Menelion Elensúle: https://github.com/Oire +//! author : Martin Groller : https://github.com/MadMG + +import moment from '../moment'; + +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]; +} + +export default moment.defineLocale('de-at', { + months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort : 'Jän._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: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay: '[Heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[Morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[Gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + 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 + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/de.js b/bower_components/moment/src/locale/de.js new file mode 100644 index 0000000..58c0c30 --- /dev/null +++ b/bower_components/moment/src/locale/de.js @@ -0,0 +1,66 @@ +//! moment.js locale configuration +//! locale : german (de) +//! author : lluchs : https://github.com/lluchs +//! author: Menelion Elensúle: https://github.com/Oire + +import moment from '../moment'; + +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]; +} + +export default moment.defineLocale('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: 'HH:mm', + LTS: 'HH:mm:ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay: '[Heute um] LT [Uhr]', + sameElse: 'L', + nextDay: '[Morgen um] LT [Uhr]', + nextWeek: 'dddd [um] LT [Uhr]', + lastDay: '[Gestern um] LT [Uhr]', + lastWeek: '[letzten] dddd [um] LT [Uhr]' + }, + 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 + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/el.js b/bower_components/moment/src/locale/el.js new file mode 100644 index 0000000..8830ada --- /dev/null +++ b/bower_components/moment/src/locale/el.js @@ -0,0 +1,85 @@ +//! moment.js locale configuration +//! locale : modern greek (el) +//! author : Aggelos Karalias : https://github.com/mehiel + +import moment from '../moment'; + +export default moment.defineLocale('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 ? 'πμ' : 'ΠΜ'; + } + }, + isPM : function (input) { + return ((input + '').toLowerCase()[0] === 'μ'); + }, + meridiemParse : /[ΠΜ]\.?Μ?\.?/i, + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss 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 : function () { + switch (this.day()) { + case 6: + return '[το προηγούμενο] dddd [{}] LT'; + default: + return '[την προηγούμενη] dddd [{}] LT'; + } + }, + sameElse : 'L' + }, + calendar : function (key, mom) { + var output = this._calendarEl[key], + hours = mom && mom.hours(); + if (typeof output === 'function') { + output = output.apply(mom); + } + 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 χρόνια' + }, + ordinalParse: /\d{1,2}η/, + ordinal: '%dη', + 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/bower_components/moment/src/locale/en-au.js b/bower_components/moment/src/locale/en-au.js new file mode 100644 index 0000000..a06b6cb --- /dev/null +++ b/bower_components/moment/src/locale/en-au.js @@ -0,0 +1,57 @@ +//! moment.js locale configuration +//! locale : australian english (en-au) + +import moment from '../moment'; + +export default moment.defineLocale('en-au', { + 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', + LTS : 'h:mm:ss 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' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + 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/bower_components/moment/src/locale/en-ca.js b/bower_components/moment/src/locale/en-ca.js new file mode 100644 index 0000000..b33f8ab --- /dev/null +++ b/bower_components/moment/src/locale/en-ca.js @@ -0,0 +1,54 @@ +//! moment.js locale configuration +//! locale : canadian english (en-ca) +//! author : Jonathan Abourbih : https://github.com/jonbca + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'h:mm:ss 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' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + 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/bower_components/moment/src/locale/en-gb.js b/bower_components/moment/src/locale/en-gb.js new file mode 100644 index 0000000..09961dd --- /dev/null +++ b/bower_components/moment/src/locale/en-gb.js @@ -0,0 +1,58 @@ +//! moment.js locale configuration +//! locale : great britain english (en-gb) +//! author : Chris Gedrim : https://github.com/chrisgedrim + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'HH:mm:ss', + 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' + }, + ordinalParse: /\d{1,2}(st|nd|rd|th)/, + 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/bower_components/moment/src/locale/eo.js b/bower_components/moment/src/locale/eo.js new file mode 100644 index 0000000..54ecf79 --- /dev/null +++ b/bower_components/moment/src/locale/eo.js @@ -0,0 +1,64 @@ +//! moment.js locale configuration +//! locale : 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! + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + meridiemParse: /[ap]\.t\.m/i, + isPM: function (input) { + return input.charAt(0).toLowerCase() === 'p'; + }, + 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' + }, + ordinalParse: /\d{1,2}a/, + 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/bower_components/moment/src/locale/es.js b/bower_components/moment/src/locale/es.js new file mode 100644 index 0000000..c9ea1f5 --- /dev/null +++ b/bower_components/moment/src/locale/es.js @@ -0,0 +1,70 @@ +//! moment.js locale configuration +//! locale : spanish (es) +//! author : Julio Napurí : https://github.com/julionc + +import moment from '../moment'; + +var monthsShortDot = 'Ene._Feb._Mar._Abr._May._Jun._Jul._Ago._Sep._Oct._Nov._Dic.'.split('_'), + monthsShort = 'Ene_Feb_Mar_Abr_May_Jun_Jul_Ago_Sep_Oct_Nov_Dic'.split('_'); + +export default moment.defineLocale('es', { + months : 'Enero_Febrero_Marzo_Abril_Mayo_Junio_Julio_Agosto_Septiembre_Octubre_Noviembre_Diciembre'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShort[m.month()]; + } else { + return monthsShortDot[m.month()]; + } + }, + 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', + LTS : 'LT:ss', + 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' + }, + ordinalParse : /\d{1,2}º/, + 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/bower_components/moment/src/locale/et.js b/bower_components/moment/src/locale/et.js new file mode 100644 index 0000000..68cbad9 --- /dev/null +++ b/bower_components/moment/src/locale/et.js @@ -0,0 +1,71 @@ +//! moment.js locale configuration +//! locale : estonian (et) +//! author : Henry Kehlmann : https://github.com/madhenry +//! improvements : Illimar Tambek : https://github.com/ragulka + +import moment from '../moment'; + +function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'], + 'm' : ['ühe minuti', 'üks minut'], + 'mm': [number + ' minuti', number + ' minutit'], + 'h' : ['ühe tunni', 'tund aega', 'üks tund'], + 'hh': [number + ' tunni', number + ' tundi'], + 'd' : ['ühe päeva', 'üks päev'], + 'M' : ['kuu aja', 'kuu aega', 'üks kuu'], + 'MM': [number + ' kuu', number + ' kuud'], + 'y' : ['ühe aasta', 'aasta', 'üks aasta'], + 'yy': [number + ' aasta', number + ' aastat'] + }; + if (withoutSuffix) { + return format[key][2] ? format[key][2] : format[key][1]; + } + return isFuture ? format[key][0] : format[key][1]; +} + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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 : processRelativeTime, + m : processRelativeTime, + mm : processRelativeTime, + h : processRelativeTime, + hh : processRelativeTime, + d : processRelativeTime, + dd : '%d päeva', + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/eu.js b/bower_components/moment/src/locale/eu.js new file mode 100644 index 0000000..2a05907 --- /dev/null +++ b/bower_components/moment/src/locale/eu.js @@ -0,0 +1,55 @@ +//! moment.js locale configuration +//! locale : euskara (eu) +//! author : Eneko Illarramendi : https://github.com/eillarra + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/fa.js b/bower_components/moment/src/locale/fa.js new file mode 100644 index 0000000..e898adf --- /dev/null +++ b/bower_components/moment/src/locale/fa.js @@ -0,0 +1,96 @@ +//! moment.js locale configuration +//! locale : Persian (fa) +//! author : Ebrahim Byagowi : https://github.com/ebraminio + +import moment from '../moment'; + +var symbolMap = { + '1': '۱', + '2': '۲', + '3': '۳', + '4': '۴', + '5': '۵', + '6': '۶', + '7': '۷', + '8': '۸', + '9': '۹', + '0': '۰' +}, numberMap = { + '۱': '1', + '۲': '2', + '۳': '3', + '۴': '4', + '۵': '5', + '۶': '6', + '۷': '7', + '۸': '8', + '۹': '9', + '۰': '0' +}; + +export default moment.defineLocale('fa', { + months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'), + weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'), + weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd, D MMMM YYYY LT' + }, + meridiemParse: /قبل از ظهر|بعد از ظهر/, + isPM: function (input) { + return /بعد از ظهر/.test(input); + }, + 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, '،'); + }, + ordinalParse: /\d{1,2}م/, + 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/bower_components/moment/src/locale/fi.js b/bower_components/moment/src/locale/fi.js new file mode 100644 index 0000000..ee38516 --- /dev/null +++ b/bower_components/moment/src/locale/fi.js @@ -0,0 +1,98 @@ +//! moment.js locale configuration +//! locale : finnish (fi) +//! author : Tarmo Aidantausta : https://github.com/bleadof + +import moment from '../moment'; + +var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '), + numbersFuture = [ + 'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden', + numbersPast[7], numbersPast[8], numbersPast[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 = verbalNumber(number, isFuture) + ' ' + result; + return result; +} +function verbalNumber(number, isFuture) { + return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number; +} + +export default moment.defineLocale('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', + LTS : 'HH.mm.ss', + 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 + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/fo.js b/bower_components/moment/src/locale/fo.js new file mode 100644 index 0000000..28a8e17 --- /dev/null +++ b/bower_components/moment/src/locale/fo.js @@ -0,0 +1,51 @@ +//! moment.js locale configuration +//! locale : faroese (fo) +//! author : Ragnar Johannesen : https://github.com/ragnar123 + +import moment from '../moment'; + +export default moment.defineLocale('fo', { + months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'), + monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'), + weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'), + weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'), + weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D. MMMM, YYYY LT' + }, + calendar : { + sameDay : '[Í dag kl.] LT', + nextDay : '[Í morgin kl.] LT', + nextWeek : 'dddd [kl.] LT', + lastDay : '[Í gjár kl.] LT', + lastWeek : '[síðstu] dddd [kl] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'um %s', + past : '%s síðani', + s : 'fá sekund', + m : 'ein minutt', + mm : '%d minuttir', + h : 'ein tími', + hh : '%d tímar', + d : 'ein dagur', + dd : '%d dagar', + M : 'ein mánaði', + MM : '%d mánaðir', + y : 'eitt ár', + yy : '%d ár' + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/fr-ca.js b/bower_components/moment/src/locale/fr-ca.js new file mode 100644 index 0000000..ef95bd2 --- /dev/null +++ b/bower_components/moment/src/locale/fr-ca.js @@ -0,0 +1,49 @@ +//! moment.js locale configuration +//! locale : canadian french (fr-ca) +//! author : Jonathan Abourbih : https://github.com/jonbca + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(er|)/, + ordinal : function (number) { + return number + (number === 1 ? 'er' : ''); + } +}); + diff --git a/bower_components/moment/src/locale/fr.js b/bower_components/moment/src/locale/fr.js new file mode 100644 index 0000000..7492f85 --- /dev/null +++ b/bower_components/moment/src/locale/fr.js @@ -0,0 +1,53 @@ +//! moment.js locale configuration +//! locale : french (fr) +//! author : John Fischer : https://github.com/jfroffice + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(er|)/, + 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/bower_components/moment/src/locale/fy.js b/bower_components/moment/src/locale/fy.js new file mode 100644 index 0000000..2ccf179 --- /dev/null +++ b/bower_components/moment/src/locale/fy.js @@ -0,0 +1,62 @@ +//! moment.js locale configuration +//! locale : frisian (fy) +//! author : Robin van der Vliet : https://github.com/robin0van0der0v + +import moment from '../moment'; + +var monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_'), + monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'); + +export default moment.defineLocale('fy', { + months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'), + monthsShort : function (m, format) { + if (/-MMM-/.test(format)) { + return monthsShortWithoutDots[m.month()]; + } else { + return monthsShortWithDots[m.month()]; + } + }, + weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'), + weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'), + weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD-MM-YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'dddd D MMMM YYYY LT' + }, + calendar : { + sameDay: '[hjoed om] LT', + nextDay: '[moarn om] LT', + nextWeek: 'dddd [om] LT', + lastDay: '[juster om] LT', + lastWeek: '[ôfrûne] dddd [om] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'oer %s', + past : '%s lyn', + s : 'in pear sekonden', + m : 'ien minút', + mm : '%d minuten', + h : 'ien oere', + hh : '%d oeren', + d : 'ien dei', + dd : '%d dagen', + M : 'ien moanne', + MM : '%d moannen', + y : 'ien jier', + yy : '%d jierren' + }, + ordinalParse: /\d{1,2}(ste|de)/, + 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/bower_components/moment/src/locale/gl.js b/bower_components/moment/src/locale/gl.js new file mode 100644 index 0000000..4413809 --- /dev/null +++ b/bower_components/moment/src/locale/gl.js @@ -0,0 +1,66 @@ +//! moment.js locale configuration +//! locale : galician (gl) +//! author : Juan G. Hurtado : https://github.com/juanghurtado + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse : /\d{1,2}º/, + 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/bower_components/moment/src/locale/he.js b/bower_components/moment/src/locale/he.js new file mode 100644 index 0000000..dd4f2d2 --- /dev/null +++ b/bower_components/moment/src/locale/he.js @@ -0,0 +1,73 @@ +//! moment.js locale configuration +//! locale : Hebrew (he) +//! author : Tomer Cohen : https://github.com/tomer +//! author : Moshe Simantov : https://github.com/DevelopmentIL +//! author : Tal Ater : https://github.com/TalAter + +import moment from '../moment'; + +export default moment.defineLocale('he', { + months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'), + monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'), + weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'), + weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'), + weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : function (number) { + if (number === 2) { + return 'שעתיים'; + } + return number + ' שעות'; + }, + d : 'יום', + dd : function (number) { + if (number === 2) { + return 'יומיים'; + } + return number + ' ימים'; + }, + M : 'חודש', + MM : function (number) { + if (number === 2) { + return 'חודשיים'; + } + return number + ' חודשים'; + }, + y : 'שנה', + yy : function (number) { + if (number === 2) { + return 'שנתיים'; + } else if (number % 10 === 0 && number !== 10) { + return number + ' שנה'; + } + return number + ' שנים'; + } + } +}); + diff --git a/bower_components/moment/src/locale/hi.js b/bower_components/moment/src/locale/hi.js new file mode 100644 index 0000000..3d56839 --- /dev/null +++ b/bower_components/moment/src/locale/hi.js @@ -0,0 +1,114 @@ +//! moment.js locale configuration +//! locale : hindi (hi) +//! author : Mayank Singhal : https://github.com/mayanksinghal + +import moment from '../moment'; + +var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' +}, +numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' +}; + +export default moment.defineLocale('hi', { + months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'), + monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'), + weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm बजे', + LTS : 'A h:mm:ss बजे', + 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. + meridiemParse: /रात|सुबह|दोपहर|शाम/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सुबह') { + return hour; + } else if (meridiem === 'दोपहर') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'शाम') { + return hour + 12; + } + }, + 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/bower_components/moment/src/locale/hr.js b/bower_components/moment/src/locale/hr.js new file mode 100644 index 0000000..eab62df --- /dev/null +++ b/bower_components/moment/src/locale/hr.js @@ -0,0 +1,131 @@ +//! moment.js locale configuration +//! locale : hrvatski (hr) +//! author : Bojan Marković : https://github.com/bmarkovic + +import moment from '../moment'; + +function translate(number, withoutSuffix, key) { + var result = number + ' '; + switch (key) { + case 'm': + return withoutSuffix ? 'jedna minuta' : 'jedne minute'; + case 'mm': + if (number === 1) { + result += 'minuta'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'minute'; + } else { + result += 'minuta'; + } + return result; + case 'h': + return withoutSuffix ? 'jedan sat' : 'jednog sata'; + case 'hh': + if (number === 1) { + result += 'sat'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'sata'; + } else { + result += 'sati'; + } + return result; + case 'dd': + if (number === 1) { + result += 'dan'; + } else { + result += 'dana'; + } + return result; + case 'MM': + if (number === 1) { + result += 'mjesec'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'mjeseca'; + } else { + result += 'mjeseci'; + } + return result; + case 'yy': + if (number === 1) { + result += 'godina'; + } else if (number === 2 || number === 3 || number === 4) { + result += 'godine'; + } else { + result += 'godina'; + } + return result; + } +} + +export default moment.defineLocale('hr', { + months : 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_'), + monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'), + weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'), + weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'), + weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + L : 'DD. MM. YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY LT', + LLLL : 'dddd, D. MMMM YYYY LT' + }, + calendar : { + sameDay : '[danas u] LT', + nextDay : '[sutra u] LT', + nextWeek : function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[jučer u] LT', + lastWeek : function () { + switch (this.day()) { + case 0: + case 3: + return '[prošlu] dddd [u] LT'; + case 6: + return '[prošle] [subote] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prošli] dddd [u] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'par sekundi', + m : translate, + mm : translate, + h : translate, + hh : translate, + d : 'dan', + dd : translate, + M : 'mjesec', + MM : translate, + y : 'godinu', + yy : translate + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/hu.js b/bower_components/moment/src/locale/hu.js new file mode 100644 index 0000000..9359a3c --- /dev/null +++ b/bower_components/moment/src/locale/hu.js @@ -0,0 +1,100 @@ +//! moment.js locale configuration +//! locale : hungarian (hu) +//! author : Adam Brunner : https://github.com/adambrunner + +import moment from '../moment'; + +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]'; +} + +export default moment.defineLocale('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 : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'), + weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + L : 'YYYY.MM.DD.', + LL : 'YYYY. MMMM D.', + LLL : 'YYYY. MMMM D., LT', + LLLL : 'YYYY. MMMM D., dddd LT' + }, + meridiemParse: /de|du/i, + isPM: function (input) { + return input.charAt(1).toLowerCase() === 'u'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 12) { + return isLower === true ? 'de' : 'DE'; + } else { + return isLower === true ? 'du' : 'DU'; + } + }, + 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 + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/hy-am.js b/bower_components/moment/src/locale/hy-am.js new file mode 100644 index 0000000..fdaac2f --- /dev/null +++ b/bower_components/moment/src/locale/hy-am.js @@ -0,0 +1,102 @@ +//! moment.js locale configuration +//! locale : Armenian (hy-am) +//! author : Armendarabyan : https://github.com/armendarabyan + +import moment from '../moment'; + +function monthsCaseReplace(m, format) { + var months = { + 'nominative': 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_'), + 'accusative': 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_') + }, + nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; +} +function monthsShortCaseReplace(m, format) { + var monthsShort = 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'); + return monthsShort[m.month()]; +} +function weekdaysCaseReplace(m, format) { + var weekdays = 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'); + return weekdays[m.day()]; +} + +export default moment.defineLocale('hy-am', { + months : monthsCaseReplace, + monthsShort : monthsShortCaseReplace, + weekdays : weekdaysCaseReplace, + weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 'dddd [օրը ժամը] LT'; + }, + lastWeek: function () { + 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 տարի' + }, + meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/, + isPM: function (input) { + return /^(ցերեկվա|երեկոյան)$/.test(input); + }, + meridiem : function (hour) { + if (hour < 4) { + return 'գիշերվա'; + } else if (hour < 12) { + return 'առավոտվա'; + } else if (hour < 17) { + return 'ցերեկվա'; + } else { + return 'երեկոյան'; + } + }, + ordinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/, + ordinal: function (number, period) { + switch (period) { + case 'DDD': + case 'w': + case 'W': + case 'DDDo': + if (number === 1) { + return number + '-ին'; + } + 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/bower_components/moment/src/locale/id.js b/bower_components/moment/src/locale/id.js new file mode 100644 index 0000000..8af7f02 --- /dev/null +++ b/bower_components/moment/src/locale/id.js @@ -0,0 +1,74 @@ +//! moment.js locale configuration +//! locale : Bahasa Indonesia (id) +//! author : Mohammad Satrio Utomo : https://github.com/tyok +//! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] LT', + LLLL : 'dddd, D MMMM YYYY [pukul] LT' + }, + meridiemParse: /pagi|siang|sore|malam/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'siang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sore' || meridiem === 'malam') { + return hour + 12; + } + }, + 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/bower_components/moment/src/locale/is.js b/bower_components/moment/src/locale/is.js new file mode 100644 index 0000000..13b8815 --- /dev/null +++ b/bower_components/moment/src/locale/is.js @@ -0,0 +1,118 @@ +//! moment.js locale configuration +//! locale : icelandic (is) +//! author : Hinrik Örn Sigurðsson : https://github.com/hinrik + +import moment from '../moment'; + +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'); + } +} + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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 + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/it.js b/bower_components/moment/src/locale/it.js new file mode 100644 index 0000000..63f34ac --- /dev/null +++ b/bower_components/moment/src/locale/it.js @@ -0,0 +1,61 @@ +//! moment.js locale configuration +//! locale : italian (it) +//! author : Lorenzo : https://github.com/aliem +//! author: Mattia Larentis: https://github.com/nostalgiaz + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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: function () { + switch (this.day()) { + case 0: + return '[la scorsa] dddd [alle] LT'; + default: + return '[lo scorso] dddd [alle] LT'; + } + }, + sameElse: 'L' + }, + relativeTime : { + future : function (s) { + return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s; + }, + past : '%s fa', + s : 'alcuni 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' + }, + ordinalParse : /\d{1,2}º/, + 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/bower_components/moment/src/locale/ja.js b/bower_components/moment/src/locale/ja.js new file mode 100644 index 0000000..1f9b865 --- /dev/null +++ b/bower_components/moment/src/locale/ja.js @@ -0,0 +1,56 @@ +//! moment.js locale configuration +//! locale : japanese (ja) +//! author : LI Long : https://github.com/baryon + +import moment from '../moment'; + +export default moment.defineLocale('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分', + LTS : 'LTs秒', + L : 'YYYY/MM/DD', + LL : 'YYYY年M月D日', + LLL : 'YYYY年M月D日LT', + LLLL : 'YYYY年M月D日LT dddd' + }, + meridiemParse: /午前|午後/i, + isPM : function (input) { + return input === '午後'; + }, + 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/bower_components/moment/src/locale/jv.js b/bower_components/moment/src/locale/jv.js new file mode 100644 index 0000000..b5401a0 --- /dev/null +++ b/bower_components/moment/src/locale/jv.js @@ -0,0 +1,73 @@ +//! moment.js locale configuration +//! locale : Boso Jowo (jv) +//! author : Rony Lantip : https://github.com/lantip +//! reference: http://jv.wikipedia.org/wiki/Basa_Jawa + +import moment from '../moment'; + +export default moment.defineLocale('jv', { + months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'), + monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'), + weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'), + weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'), + weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'), + longDateFormat : { + LT : 'HH.mm', + LTS : 'LT.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] LT', + LLLL : 'dddd, D MMMM YYYY [pukul] LT' + }, + meridiemParse: /enjing|siyang|sonten|ndalu/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'enjing') { + return hour; + } else if (meridiem === 'siyang') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'sonten' || meridiem === 'ndalu') { + return hour + 12; + } + }, + meridiem : function (hours, minutes, isLower) { + if (hours < 11) { + return 'enjing'; + } else if (hours < 15) { + return 'siyang'; + } else if (hours < 19) { + return 'sonten'; + } else { + return 'ndalu'; + } + }, + calendar : { + sameDay : '[Dinten puniko pukul] LT', + nextDay : '[Mbenjang pukul] LT', + nextWeek : 'dddd [pukul] LT', + lastDay : '[Kala wingi pukul] LT', + lastWeek : 'dddd [kepengker pukul] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'wonten ing %s', + past : '%s ingkang kepengker', + s : 'sawetawis detik', + m : 'setunggal menit', + mm : '%d menit', + h : 'setunggal jam', + hh : '%d jam', + d : 'sedinten', + dd : '%d dinten', + M : 'sewulan', + MM : '%d wulan', + y : 'setaun', + yy : '%d taun' + }, + 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/bower_components/moment/src/locale/ka.js b/bower_components/moment/src/locale/ka.js new file mode 100644 index 0000000..a750b2a --- /dev/null +++ b/bower_components/moment/src/locale/ka.js @@ -0,0 +1,94 @@ +//! moment.js locale configuration +//! locale : Georgian (ka) +//! author : Irakli Janiashvili : https://github.com/irakli-janiashvili + +import moment from '../moment'; + +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()]; +} + +export default moment.defineLocale('ka', { + months : monthsCaseReplace, + monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'), + weekdays : weekdaysCaseReplace, + weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'), + weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'), + longDateFormat : { + LT : 'h:mm A', + LTS : 'h:mm:ss 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 წელი' + }, + ordinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/, + 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/bower_components/moment/src/locale/km.js b/bower_components/moment/src/locale/km.js new file mode 100644 index 0000000..db9147e --- /dev/null +++ b/bower_components/moment/src/locale/km.js @@ -0,0 +1,49 @@ +//! moment.js locale configuration +//! locale : khmer (km) +//! author : Kruy Vanna : https://github.com/kruyvanna + +import moment from '../moment'; + +export default moment.defineLocale('km', { + months: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + monthsShort: 'មករា_កុម្ភៈ_មិនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'), + weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'), + longDateFormat: { + LT: 'HH:mm', + LTS : 'LT:ss', + 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: 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/bower_components/moment/src/locale/ko.js b/bower_components/moment/src/locale/ko.js new file mode 100644 index 0000000..a56aee0 --- /dev/null +++ b/bower_components/moment/src/locale/ko.js @@ -0,0 +1,59 @@ +//! moment.js locale configuration +//! locale : korean (ko) +//! +//! authors +//! +//! - Kyungwook, Park : https://github.com/kyungw00k +//! - Jeeeyul Lee <jeeeyul@gmail.com> + +import moment from '../moment'; + +export default moment.defineLocale('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시 m분', + LTS : 'A h시 m분 s초', + L : 'YYYY.MM.DD', + LL : 'YYYY년 MMMM D일', + LLL : 'YYYY년 MMMM D일 LT', + LLLL : 'YYYY년 MMMM D일 dddd LT' + }, + 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년' + }, + ordinalParse : /\d{1,2}일/, + ordinal : '%d일', + meridiemParse : /오전|오후/, + isPM : function (token) { + return token === '오후'; + }, + meridiem : function (hour, minute, isUpper) { + return hour < 12 ? '오전' : '오후'; + } +}); + diff --git a/bower_components/moment/src/locale/lb.js b/bower_components/moment/src/locale/lb.js new file mode 100644 index 0000000..6cc6d55 --- /dev/null +++ b/bower_components/moment/src/locale/lb.js @@ -0,0 +1,125 @@ +//! moment.js locale configuration +//! locale : Luxembourgish (lb) +//! author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz + +import moment from '../moment'; + +function processRelativeTime(number, withoutSuffix, key, isFuture) { + var format = { + 'm': ['eng Minutt', 'enger Minutt'], + 'h': ['eng Stonn', 'enger Stonn'], + 'd': ['een Dag', 'engem Dag'], + 'M': ['ee Mount', 'engem Mount'], + 'y': ['ee Joer', 'engem Joer'] + }; + return withoutSuffix ? format[key][0] : format[key][1]; +} +function processFutureTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'a ' + string; + } + return 'an ' + string; +} +function processPastTime(string) { + var number = string.substr(0, string.indexOf(' ')); + if (eifelerRegelAppliesToNumber(number)) { + return 'viru ' + string; + } + return 'virun ' + string; +} +/** + * Returns true if the word before the given number loses the '-n' ending. + * e.g. 'an 10 Deeg' but 'a 5 Deeg' + * + * @param number {integer} + * @returns {boolean} + */ +function eifelerRegelAppliesToNumber(number) { + number = parseInt(number, 10); + if (isNaN(number)) { + return false; + } + if (number < 0) { + // Negative Number --> always true + return true; + } else if (number < 10) { + // Only 1 digit + if (4 <= number && number <= 7) { + return true; + } + return false; + } else if (number < 100) { + // 2 digits + var lastDigit = number % 10, firstDigit = number / 10; + if (lastDigit === 0) { + return eifelerRegelAppliesToNumber(firstDigit); + } + return eifelerRegelAppliesToNumber(lastDigit); + } else if (number < 10000) { + // 3 or 4 digits --> recursively check first digit + while (number >= 10) { + number = number / 10; + } + return eifelerRegelAppliesToNumber(number); + } else { + // Anything larger than 4 digits: recursively check first n-3 digits + number = number / 1000; + return eifelerRegelAppliesToNumber(number); + } +} + +export default moment.defineLocale('lb', { + months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'), + monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'), + weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'), + weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'), + weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'), + longDateFormat: { + LT: 'H:mm [Auer]', + LTS: 'H:mm:ss [Auer]', + L: 'DD.MM.YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY LT', + LLLL: 'dddd, D. MMMM YYYY LT' + }, + calendar: { + sameDay: '[Haut um] LT', + sameElse: 'L', + nextDay: '[Muer um] LT', + nextWeek: 'dddd [um] LT', + lastDay: '[Gëschter um] LT', + lastWeek: function () { + // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule + switch (this.day()) { + case 2: + case 4: + return '[Leschten] dddd [um] LT'; + default: + return '[Leschte] dddd [um] LT'; + } + } + }, + relativeTime : { + future : processFutureTime, + past : processPastTime, + s : 'e puer Sekonnen', + m : processRelativeTime, + mm : '%d Minutten', + h : processRelativeTime, + hh : '%d Stonnen', + d : processRelativeTime, + dd : '%d Deeg', + M : processRelativeTime, + MM : '%d Méint', + y : processRelativeTime, + yy : '%d Joer' + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/lt.js b/bower_components/moment/src/locale/lt.js new file mode 100644 index 0000000..8095163 --- /dev/null +++ b/bower_components/moment/src/locale/lt.js @@ -0,0 +1,106 @@ +//! moment.js locale configuration +//! locale : Lithuanian (lt) +//! author : Mindaugas Mozūras : https://github.com/mmozuras + +import moment from '../moment'; + +var units = { + 'm' : 'minutė_minutės_minutę', + 'mm': 'minutės_minučių_minutes', + 'h' : 'valanda_valandos_valandą', + 'hh': 'valandos_valandų_valandas', + 'd' : 'diena_dienos_dieną', + 'dd': 'dienos_dienų_dienas', + 'M' : 'mėnuo_mėnesio_mėnesį', + 'MM': 'mėnesiai_mėnesių_mėnesius', + 'y' : 'metai_metų_metus', + 'yy': 'metai_metų_metus' +}, +weekDays = 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'); +function translateSeconds(number, withoutSuffix, key, isFuture) { + if (withoutSuffix) { + return 'kelios sekundės'; + } else { + return isFuture ? 'kelių sekundžių' : 'kelias sekundes'; + } +} +function translateSingular(number, withoutSuffix, key, isFuture) { + return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]); +} +function special(number) { + return number % 10 === 0 || (number > 10 && number < 20); +} +function forms(key) { + return units[key].split('_'); +} +function translate(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + if (number === 1) { + return result + translateSingular(number, withoutSuffix, key[0], isFuture); + } else if (withoutSuffix) { + return result + (special(number) ? forms(key)[1] : forms(key)[0]); + } else { + if (isFuture) { + return result + forms(key)[1]; + } else { + return result + (special(number) ? forms(key)[1] : forms(key)[2]); + } + } +} +function relativeWeekDay(moment, format) { + var nominative = format.indexOf('dddd HH:mm') === -1, + weekDay = weekDays[moment.day()]; + return nominative ? weekDay : weekDay.substring(0, weekDay.length - 2) + 'į'; +} + +export default moment.defineLocale('lt', { + months : 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'), + monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'), + weekdays : relativeWeekDay, + weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'), + weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'YYYY-MM-DD', + LL : 'YYYY [m.] MMMM D [d.]', + LLL : 'YYYY [m.] MMMM D [d.], LT [val.]', + LLLL : 'YYYY [m.] MMMM D [d.], dddd, LT [val.]', + l : 'YYYY-MM-DD', + ll : 'YYYY [m.] MMMM D [d.]', + lll : 'YYYY [m.] MMMM D [d.], LT [val.]', + llll : 'YYYY [m.] MMMM D [d.], ddd, LT [val.]' + }, + calendar : { + sameDay : '[Šiandien] LT', + nextDay : '[Rytoj] LT', + nextWeek : 'dddd LT', + lastDay : '[Vakar] LT', + lastWeek : '[Praėjusį] dddd LT', + sameElse : 'L' + }, + relativeTime : { + future : 'po %s', + past : 'prieš %s', + s : translateSeconds, + m : translateSingular, + mm : translate, + h : translateSingular, + hh : translate, + d : translateSingular, + dd : translate, + M : translateSingular, + MM : translate, + y : translateSingular, + yy : translate + }, + ordinalParse: /\d{1,2}-oji/, + ordinal : function (number) { + return number + '-oji'; + }, + 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/bower_components/moment/src/locale/lv.js b/bower_components/moment/src/locale/lv.js new file mode 100644 index 0000000..b37cb5c --- /dev/null +++ b/bower_components/moment/src/locale/lv.js @@ -0,0 +1,87 @@ +//! moment.js locale configuration +//! locale : latvian (lv) +//! author : Kristaps Karlsons : https://github.com/skakri +//! author : Jānis Elmeris : https://github.com/JanisE + +import moment from '../moment'; + +var units = { + 'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'), + 'h': 'stundas_stundām_stunda_stundas'.split('_'), + 'hh': 'stundas_stundām_stunda_stundas'.split('_'), + 'd': 'dienas_dienām_diena_dienas'.split('_'), + 'dd': 'dienas_dienām_diena_dienas'.split('_'), + 'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'), + 'y': 'gada_gadiem_gads_gadi'.split('_'), + 'yy': 'gada_gadiem_gads_gadi'.split('_') +}; +/** + * @param withoutSuffix boolean true = a length of time; false = before/after a period of time. + */ +function format(forms, number, withoutSuffix) { + if (withoutSuffix) { + // E.g. "21 minūte", "3 minūtes". + return number % 10 === 1 && number !== 11 ? forms[2] : forms[3]; + } else { + // E.g. "21 minūtes" as in "pēc 21 minūtes". + // E.g. "3 minūtēm" as in "pēc 3 minūtēm". + return number % 10 === 1 && number !== 11 ? forms[0] : forms[1]; + } +} +function relativeTimeWithPlural(number, withoutSuffix, key) { + return number + ' ' + format(units[key], number, withoutSuffix); +} +function relativeTimeWithSingular(number, withoutSuffix, key) { + return format(units[key], number, withoutSuffix); +} +function relativeSeconds(number, withoutSuffix) { + return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm'; +} + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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 : 'pēc %s', + past : 'pirms %s', + s : relativeSeconds, + m : relativeTimeWithSingular, + mm : relativeTimeWithPlural, + h : relativeTimeWithSingular, + hh : relativeTimeWithPlural, + d : relativeTimeWithSingular, + dd : relativeTimeWithPlural, + M : relativeTimeWithSingular, + MM : relativeTimeWithPlural, + y : relativeTimeWithSingular, + yy : relativeTimeWithPlural + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/me.js b/bower_components/moment/src/locale/me.js new file mode 100644 index 0000000..2c356da --- /dev/null +++ b/bower_components/moment/src/locale/me.js @@ -0,0 +1,99 @@ +//! moment.js locale configuration +//! locale : Montenegrin (me) +//! author : Miodrag Nikač <miodrag@restartit.me> : https://github.com/miodragnikac + +import moment from '../moment'; + +var translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jednog minuta'], + mm: ['minut', 'minuta', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mjesec', 'mjeseca', 'mjeseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + translator.correctGrammaticalCase(number, wordKey); + } + } +}; + +export default moment.defineLocale('me', { + months: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'], + monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'], + weekdays: ['nedjelja', 'ponedjeljak', 'utorak', 'srijeda', 'četvrtak', 'petak', 'subota'], + weekdaysShort: ['ned.', 'pon.', 'uto.', 'sri.', 'čet.', 'pet.', 'sub.'], + weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'], + longDateFormat: { + LT: 'H:mm', + LTS : 'LT:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY LT', + LLLL: 'dddd, D. MMMM YYYY LT' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sjutra u] LT', + + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedjelju] [u] LT'; + case 3: + return '[u] [srijedu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedjelje] [u] LT', + '[prošlog] [ponedjeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srijede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'prije %s', + s : 'nekoliko sekundi', + m : translator.translate, + mm : translator.translate, + h : translator.translate, + hh : translator.translate, + d : 'dan', + dd : translator.translate, + M : 'mjesec', + MM : translator.translate, + y : 'godinu', + yy : translator.translate + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/mk.js b/bower_components/moment/src/locale/mk.js new file mode 100644 index 0000000..80c522d --- /dev/null +++ b/bower_components/moment/src/locale/mk.js @@ -0,0 +1,81 @@ +//! moment.js locale configuration +//! locale : macedonian (mk) +//! author : Borislav Mickov : https://github.com/B0k0 + +import moment from '../moment'; + +export default moment.defineLocale('mk', { + months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'), + monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'), + weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'), + weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'), + weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'), + longDateFormat : { + LT : 'H:mm', + LTS : 'LT:ss', + 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 години' + }, + ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/, + 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/bower_components/moment/src/locale/ml.js b/bower_components/moment/src/locale/ml.js new file mode 100644 index 0000000..cbb9056 --- /dev/null +++ b/bower_components/moment/src/locale/ml.js @@ -0,0 +1,62 @@ +//! moment.js locale configuration +//! locale : malayalam (ml) +//! author : Floyd Pink : https://github.com/floydpink + +import moment from '../moment'; + +export default moment.defineLocale('ml', { + months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'), + monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'), + weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'), + weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'), + weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'), + longDateFormat : { + LT : 'A h:mm -നു', + LTS : 'A h:mm:ss -നു', + 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 വർഷം' + }, + meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i, + isPM : function (input) { + return /^(ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'രാത്രി'; + } else if (hour < 12) { + return 'രാവിലെ'; + } else if (hour < 17) { + return 'ഉച്ച കഴിഞ്ഞ്'; + } else if (hour < 20) { + return 'വൈകുന്നേരം'; + } else { + return 'രാത്രി'; + } + } +}); + diff --git a/bower_components/moment/src/locale/mr.js b/bower_components/moment/src/locale/mr.js new file mode 100644 index 0000000..24011a3 --- /dev/null +++ b/bower_components/moment/src/locale/mr.js @@ -0,0 +1,112 @@ +//! moment.js locale configuration +//! locale : Marathi (mr) +//! author : Harshad Kale : https://github.com/kalehv + +import moment from '../moment'; + +var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' +}, +numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' +}; + +export default moment.defineLocale('mr', { + months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'), + monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'), + weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'), + weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'), + weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'), + longDateFormat : { + LT : 'A h:mm वाजता', + LTS : 'A h:mm:ss वाजता', + 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]; + }); + }, + meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'रात्री') { + return hour < 4 ? hour : hour + 12; + } else if (meridiem === 'सकाळी') { + return hour; + } else if (meridiem === 'दुपारी') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'सायंकाळी') { + return hour + 12; + } + }, + 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/bower_components/moment/src/locale/ms-my.js b/bower_components/moment/src/locale/ms-my.js new file mode 100644 index 0000000..10bce03 --- /dev/null +++ b/bower_components/moment/src/locale/ms-my.js @@ -0,0 +1,73 @@ +//! moment.js locale configuration +//! locale : Bahasa Malaysia (ms-MY) +//! author : Weldan Jamili : https://github.com/weldan + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT.ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY [pukul] LT', + LLLL : 'dddd, D MMMM YYYY [pukul] LT' + }, + meridiemParse: /pagi|tengahari|petang|malam/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'pagi') { + return hour; + } else if (meridiem === 'tengahari') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === 'petang' || meridiem === 'malam') { + return hour + 12; + } + }, + 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/bower_components/moment/src/locale/my.js b/bower_components/moment/src/locale/my.js new file mode 100644 index 0000000..54af140 --- /dev/null +++ b/bower_components/moment/src/locale/my.js @@ -0,0 +1,84 @@ +//! moment.js locale configuration +//! locale : Burmese (my) +//! author : Squar team, mysquar.com + +import moment from '../moment'; + +var symbolMap = { + '1': '၁', + '2': '၂', + '3': '၃', + '4': '၄', + '5': '၅', + '6': '၆', + '7': '၇', + '8': '၈', + '9': '၉', + '0': '၀' +}, numberMap = { + '၁': '1', + '၂': '2', + '၃': '3', + '၄': '4', + '၅': '5', + '၆': '6', + '၇': '7', + '၈': '8', + '၉': '9', + '၀': '0' +}; + +export default moment.defineLocale('my', { + months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'), + monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'), + weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'), + weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'), + + longDateFormat: { + LT: 'HH:mm', + LTS: 'HH:mm:ss', + 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]; + }); + }, + week: { + dow: 1, // Monday is the first day of the week. + doy: 4 // The week that contains Jan 1st is the first week of the year. + } +}); + diff --git a/bower_components/moment/src/locale/nb.js b/bower_components/moment/src/locale/nb.js new file mode 100644 index 0000000..cadc224 --- /dev/null +++ b/bower_components/moment/src/locale/nb.js @@ -0,0 +1,52 @@ +//! moment.js locale configuration +//! locale : norwegian bokmål (nb) +//! authors : Espen Hovlandsdal : https://github.com/rexxars +//! Sigurd Gartmann : https://github.com/sigurdga + +import moment from '../moment'; + +export default moment.defineLocale('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_tirs_ons_tors_fre_lør'.split('_'), + weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'), + longDateFormat : { + LT : 'H.mm', + LTS : 'LT.ss', + L : 'DD.MM.YYYY', + LL : 'D. MMMM YYYY', + LLL : 'D. MMMM YYYY [kl.] LT', + LLLL : 'dddd D. MMMM YYYY [kl.] LT' + }, + calendar : { + sameDay: '[i dag kl.] LT', + nextDay: '[i morgen kl.] LT', + nextWeek: 'dddd [kl.] LT', + lastDay: '[i går kl.] LT', + lastWeek: '[forrige] dddd [kl.] 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' + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/ne.js b/bower_components/moment/src/locale/ne.js new file mode 100644 index 0000000..966db26 --- /dev/null +++ b/bower_components/moment/src/locale/ne.js @@ -0,0 +1,114 @@ +//! moment.js locale configuration +//! locale : nepali/nepalese +//! author : suvash : https://github.com/suvash + +import moment from '../moment'; + +var symbolMap = { + '1': '१', + '2': '२', + '3': '३', + '4': '४', + '5': '५', + '6': '६', + '7': '७', + '8': '८', + '9': '९', + '0': '०' +}, +numberMap = { + '१': '1', + '२': '2', + '३': '3', + '४': '4', + '५': '5', + '६': '6', + '७': '7', + '८': '8', + '९': '9', + '०': '0' +}; + +export default moment.defineLocale('ne', { + months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'), + monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'), + weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'), + weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'), + weekdaysMin : 'आइ._सो._मङ्_बु._बि._शु._श.'.split('_'), + longDateFormat : { + LT : 'Aको h:mm बजे', + LTS : 'Aको h:mm:ss बजे', + 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]; + }); + }, + meridiemParse: /राती|बिहान|दिउँसो|बेलुका|साँझ|राती/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'राती') { + return hour < 3 ? hour : hour + 12; + } else if (meridiem === 'बिहान') { + return hour; + } else if (meridiem === 'दिउँसो') { + return hour >= 10 ? hour : hour + 12; + } else if (meridiem === 'बेलुका' || meridiem === 'साँझ') { + return hour + 12; + } + }, + 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/bower_components/moment/src/locale/nl.js b/bower_components/moment/src/locale/nl.js new file mode 100644 index 0000000..f493a76 --- /dev/null +++ b/bower_components/moment/src/locale/nl.js @@ -0,0 +1,62 @@ +//! moment.js locale configuration +//! locale : dutch (nl) +//! author : Joris Röling : https://github.com/jjupiter + +import moment from '../moment'; + +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('_'); + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}(ste|de)/, + 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/bower_components/moment/src/locale/nn.js b/bower_components/moment/src/locale/nn.js new file mode 100644 index 0000000..b3f76c5 --- /dev/null +++ b/bower_components/moment/src/locale/nn.js @@ -0,0 +1,51 @@ +//! moment.js locale configuration +//! locale : norwegian nynorsk (nn) +//! author : https://github.com/mechuwind + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + L : 'DD.MM.YYYY', + 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åande] dddd [klokka] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'om %s', + past : 'for %s sidan', + s : 'nokre sekund', + m : 'eit minutt', + mm : '%d minutt', + h : 'ein time', + hh : '%d timar', + d : 'ein dag', + dd : '%d dagar', + M : 'ein månad', + MM : '%d månader', + y : 'eit år', + yy : '%d år' + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/pl.js b/bower_components/moment/src/locale/pl.js new file mode 100644 index 0000000..e458ea5 --- /dev/null +++ b/bower_components/moment/src/locale/pl.js @@ -0,0 +1,95 @@ +//! moment.js locale configuration +//! locale : polish (pl) +//! author : Rafal Hirsz : https://github.com/evoL + +import moment from '../moment'; + +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) % 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'); + } +} + +export default moment.defineLocale('pl', { + months : function (momentToFormat, format) { + if (format === '') { + // Hack: if format empty we know this is used to generate + // RegExp by moment. Give then back both valid forms of months + // in RegExp ready format. + return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')'; + } else 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', + LTS : 'LT:ss', + 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 + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/pt-br.js b/bower_components/moment/src/locale/pt-br.js new file mode 100644 index 0000000..e08e847 --- /dev/null +++ b/bower_components/moment/src/locale/pt-br.js @@ -0,0 +1,51 @@ +//! moment.js locale configuration +//! locale : brazilian portuguese (pt-br) +//! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D [de] MMMM [de] YYYY', + LLL : 'D [de] MMMM [de] YYYY [às] LT', + LLLL : 'dddd, D [de] MMMM [de] YYYY [às] 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' + }, + ordinalParse: /\d{1,2}º/, + ordinal : '%dº' +}); + diff --git a/bower_components/moment/src/locale/pt.js b/bower_components/moment/src/locale/pt.js new file mode 100644 index 0000000..71e37c6 --- /dev/null +++ b/bower_components/moment/src/locale/pt.js @@ -0,0 +1,55 @@ +//! moment.js locale configuration +//! locale : portuguese (pt) +//! author : Jefferson : https://github.com/jalex79 + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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 : 'há %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' + }, + ordinalParse: /\d{1,2}º/, + 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/bower_components/moment/src/locale/ro.js b/bower_components/moment/src/locale/ro.js new file mode 100644 index 0000000..de6cebf --- /dev/null +++ b/bower_components/moment/src/locale/ro.js @@ -0,0 +1,65 @@ +//! moment.js locale configuration +//! locale : romanian (ro) +//! author : Vlad Gurdiga : https://github.com/gurdiga +//! author : Valentin Agachi : https://github.com/avaly + +import moment from '../moment'; + +function relativeTimeWithPlural(number, withoutSuffix, key) { + var format = { + 'mm': 'minute', + 'hh': 'ore', + 'dd': 'zile', + 'MM': 'luni', + 'yy': 'ani' + }, + separator = ' '; + if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) { + separator = ' de '; + } + return number + separator + format[key]; +} + +export default moment.defineLocale('ro', { + months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'), + monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._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', + LTS : 'LT:ss', + 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 : relativeTimeWithPlural, + h : 'o oră', + hh : relativeTimeWithPlural, + d : 'o zi', + dd : relativeTimeWithPlural, + M : 'o lună', + MM : relativeTimeWithPlural, + y : 'un an', + yy : relativeTimeWithPlural + }, + 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/bower_components/moment/src/locale/ru.js b/bower_components/moment/src/locale/ru.js new file mode 100644 index 0000000..8a210a4 --- /dev/null +++ b/bower_components/moment/src/locale/ru.js @@ -0,0 +1,155 @@ +//! moment.js locale configuration +//! locale : russian (ru) +//! author : Viktorminator : https://github.com/Viktorminator +//! Author : Menelion Elensúle : https://github.com/Oire + +import moment from '../moment'; + +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': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут', + '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]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return months[nounCase][m.month()]; +} +function monthsShortCaseReplace(m, format) { + var monthsShort = { + 'nominative': 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'), + 'accusative': 'янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек'.split('_') + }, + nounCase = (/D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/).test(format) ? + 'accusative' : + 'nominative'; + return monthsShort[nounCase][m.month()]; +} +function weekdaysCaseReplace(m, format) { + var weekdays = { + 'nominative': 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'), + 'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_') + }, + nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/).test(format) ? + 'accusative' : + 'nominative'; + return weekdays[nounCase][m.day()]; +} + +export default moment.defineLocale('ru', { + months : monthsCaseReplace, + monthsShort : monthsShortCaseReplace, + weekdays : weekdaysCaseReplace, + weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'), + monthsParse : [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[й|я]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i], + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 (now) { + if (now.week() !== this.week()) { + 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'; + } + } else { + if (this.day() === 2) { + return '[Во] dddd [в] LT'; + } else { + 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 + }, + meridiemParse: /ночи|утра|дня|вечера/i, + isPM : function (input) { + return /^(дня|вечера)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночи'; + } else if (hour < 12) { + return 'утра'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечера'; + } + }, + ordinalParse: /\d{1,2}-(й|го|я)/, + 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/bower_components/moment/src/locale/si.js b/bower_components/moment/src/locale/si.js new file mode 100644 index 0000000..4f5995c --- /dev/null +++ b/bower_components/moment/src/locale/si.js @@ -0,0 +1,56 @@ +//! moment.js locale configuration +//! locale : Sinhalese (si) +//! author : Sampath Sitinamaluwa : https://github.com/sampathsris + +import moment from '../moment'; + +/*jshint -W100*/ +export default moment.defineLocale('si', { + months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'), + monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'), + weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'), + weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්රහ_සිකු_සෙන'.split('_'), + weekdaysMin : 'ඉ_ස_අ_බ_බ්ර_සි_සෙ'.split('_'), + longDateFormat : { + LT : 'a h:mm', + LTS : 'a h:mm:ss', + L : 'YYYY/MM/DD', + LL : 'YYYY MMMM D', + LLL : 'YYYY MMMM D, LT', + LLLL : 'YYYY MMMM D [වැනි] dddd, LTS' + }, + 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' + }, + ordinalParse: /\d{1,2} වැනි/, + ordinal : function (number) { + return number + ' වැනි'; + }, + meridiem : function (hours, minutes, isLower) { + if (hours > 11) { + return isLower ? 'ප.ව.' : 'පස් වරු'; + } else { + return isLower ? 'පෙ.ව.' : 'පෙර වරු'; + } + } +}); diff --git a/bower_components/moment/src/locale/sk.js b/bower_components/moment/src/locale/sk.js new file mode 100644 index 0000000..4ac38c3 --- /dev/null +++ b/bower_components/moment/src/locale/sk.js @@ -0,0 +1,149 @@ +//! moment.js locale configuration +//! locale : slovak (sk) +//! author : Martin Minka : https://github.com/k2s +//! based on work of petrbela : https://github.com/petrbela + +import moment from '../moment'; + +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; + } +} + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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 + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/sl.js b/bower_components/moment/src/locale/sl.js new file mode 100644 index 0000000..e572338 --- /dev/null +++ b/bower_components/moment/src/locale/sl.js @@ -0,0 +1,150 @@ +//! moment.js locale configuration +//! locale : slovenian (sl) +//! author : Robert Sedovšek : https://github.com/sedovsek + +import moment from '../moment'; + +function processRelativeTime(number, withoutSuffix, key, isFuture) { + var result = number + ' '; + switch (key) { + case 's': + return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami'; + case 'm': + return withoutSuffix ? 'ena minuta' : 'eno minuto'; + case 'mm': + if (number === 1) { + result += withoutSuffix ? 'minuta' : 'minuto'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'minuti' : 'minutama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'minute' : 'minutami'; + } else { + result += withoutSuffix || isFuture ? 'minut' : 'minutami'; + } + return result; + case 'h': + return withoutSuffix ? 'ena ura' : 'eno uro'; + case 'hh': + if (number === 1) { + result += withoutSuffix ? 'ura' : 'uro'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'uri' : 'urama'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'ure' : 'urami'; + } else { + result += withoutSuffix || isFuture ? 'ur' : 'urami'; + } + return result; + case 'd': + return withoutSuffix || isFuture ? 'en dan' : 'enim dnem'; + case 'dd': + if (number === 1) { + result += withoutSuffix || isFuture ? 'dan' : 'dnem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'dni' : 'dnevoma'; + } else { + result += withoutSuffix || isFuture ? 'dni' : 'dnevi'; + } + return result; + case 'M': + return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem'; + case 'MM': + if (number === 1) { + result += withoutSuffix || isFuture ? 'mesec' : 'mesecem'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'meseca' : 'mesecema'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'mesece' : 'meseci'; + } else { + result += withoutSuffix || isFuture ? 'mesecev' : 'meseci'; + } + return result; + case 'y': + return withoutSuffix || isFuture ? 'eno leto' : 'enim letom'; + case 'yy': + if (number === 1) { + result += withoutSuffix || isFuture ? 'leto' : 'letom'; + } else if (number === 2) { + result += withoutSuffix || isFuture ? 'leti' : 'letoma'; + } else if (number < 5) { + result += withoutSuffix || isFuture ? 'leta' : 'leti'; + } else { + result += withoutSuffix || isFuture ? 'let' : 'leti'; + } + return result; + } +} + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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: + return '[prejšnjo] [nedeljo] [ob] LT'; + case 3: + return '[prejšnjo] [sredo] [ob] LT'; + case 6: + return '[prejšnjo] [soboto] [ob] LT'; + case 1: + case 2: + case 4: + case 5: + return '[prejšnji] dddd [ob] LT'; + } + }, + sameElse : 'L' + }, + relativeTime : { + future : 'čez %s', + past : 'pred %s', + s : processRelativeTime, + m : processRelativeTime, + mm : processRelativeTime, + h : processRelativeTime, + hh : processRelativeTime, + d : processRelativeTime, + dd : processRelativeTime, + M : processRelativeTime, + MM : processRelativeTime, + y : processRelativeTime, + yy : processRelativeTime + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/sq.js b/bower_components/moment/src/locale/sq.js new file mode 100644 index 0000000..76172b4 --- /dev/null +++ b/bower_components/moment/src/locale/sq.js @@ -0,0 +1,60 @@ +//! moment.js locale configuration +//! locale : Albanian (sq) +//! author : Flakërim Ismani : https://github.com/flakerimi +//! author: Menelion Elensúle: https://github.com/Oire (tests) +//! author : Oerd Cukalla : https://github.com/oerd (fixes) + +import moment from '../moment'; + +export default moment.defineLocale('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 Martë_E Mërkurë_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('_'), + meridiemParse: /PD|MD/, + isPM: function (input) { + return input.charAt(0) === 'M'; + }, + meridiem : function (hours, minutes, isLower) { + return hours < 12 ? 'PD' : 'MD'; + }, + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 : '[Nesër në] LT', + nextWeek : 'dddd [në] LT', + lastDay : '[Dje në] LT', + lastWeek : 'dddd [e kaluar në] LT', + sameElse : 'L' + }, + relativeTime : { + future : 'në %s', + past : '%s më parë', + s : 'disa sekonda', + m : 'një minutë', + mm : '%d minuta', + h : 'një orë', + hh : '%d orë', + d : 'një ditë', + dd : '%d ditë', + M : 'një muaj', + MM : '%d muaj', + y : 'një vit', + yy : '%d vite' + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/sr-cyrl.js b/bower_components/moment/src/locale/sr-cyrl.js new file mode 100644 index 0000000..1da53e3 --- /dev/null +++ b/bower_components/moment/src/locale/sr-cyrl.js @@ -0,0 +1,99 @@ +//! moment.js locale configuration +//! locale : Serbian-cyrillic (sr-cyrl) +//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + +import moment from '../moment'; + +var translator = { + words: { //Different grammatical cases + m: ['један минут', 'једне минуте'], + mm: ['минут', 'минуте', 'минута'], + h: ['један сат', 'једног сата'], + hh: ['сат', 'сата', 'сати'], + dd: ['дан', 'дана', 'дана'], + MM: ['месец', 'месеца', 'месеци'], + yy: ['година', 'године', 'година'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + translator.correctGrammaticalCase(number, wordKey); + } + } +}; + +export default moment.defineLocale('sr-cyrl', { + months: ['јануар', 'фебруар', 'март', 'април', 'мај', 'јун', 'јул', 'август', 'септембар', 'октобар', 'новембар', 'децембар'], + monthsShort: ['јан.', 'феб.', 'мар.', 'апр.', 'мај', 'јун', 'јул', 'авг.', 'сеп.', 'окт.', 'нов.', 'дец.'], + weekdays: ['недеља', 'понедељак', 'уторак', 'среда', 'четвртак', 'петак', 'субота'], + weekdaysShort: ['нед.', 'пон.', 'уто.', 'сре.', 'чет.', 'пет.', 'суб.'], + weekdaysMin: ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'], + longDateFormat: { + LT: 'H:mm', + LTS : 'LT:ss', + 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: function () { + switch (this.day()) { + case 0: + return '[у] [недељу] [у] LT'; + case 3: + return '[у] [среду] [у] LT'; + case 6: + return '[у] [суботу] [у] LT'; + case 1: + case 2: + case 4: + case 5: + return '[у] dddd [у] LT'; + } + }, + lastDay : '[јуче у] LT', + lastWeek : function () { + var lastWeekDays = [ + '[прошле] [недеље] [у] LT', + '[прошлог] [понедељка] [у] LT', + '[прошлог] [уторка] [у] LT', + '[прошле] [среде] [у] LT', + '[прошлог] [четвртка] [у] LT', + '[прошлог] [петка] [у] LT', + '[прошле] [суботе] [у] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'за %s', + past : 'пре %s', + s : 'неколико секунди', + m : translator.translate, + mm : translator.translate, + h : translator.translate, + hh : translator.translate, + d : 'дан', + dd : translator.translate, + M : 'месец', + MM : translator.translate, + y : 'годину', + yy : translator.translate + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/sr.js b/bower_components/moment/src/locale/sr.js new file mode 100644 index 0000000..210c739 --- /dev/null +++ b/bower_components/moment/src/locale/sr.js @@ -0,0 +1,99 @@ +//! moment.js locale configuration +//! locale : Serbian-latin (sr) +//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j + +import moment from '../moment'; + +var translator = { + words: { //Different grammatical cases + m: ['jedan minut', 'jedne minute'], + mm: ['minut', 'minute', 'minuta'], + h: ['jedan sat', 'jednog sata'], + hh: ['sat', 'sata', 'sati'], + dd: ['dan', 'dana', 'dana'], + MM: ['mesec', 'meseca', 'meseci'], + yy: ['godina', 'godine', 'godina'] + }, + correctGrammaticalCase: function (number, wordKey) { + return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]); + }, + translate: function (number, withoutSuffix, key) { + var wordKey = translator.words[key]; + if (key.length === 1) { + return withoutSuffix ? wordKey[0] : wordKey[1]; + } else { + return number + ' ' + translator.correctGrammaticalCase(number, wordKey); + } + } +}; + +export default moment.defineLocale('sr', { + months: ['januar', 'februar', 'mart', 'april', 'maj', 'jun', 'jul', 'avgust', 'septembar', 'oktobar', 'novembar', 'decembar'], + monthsShort: ['jan.', 'feb.', 'mar.', 'apr.', 'maj', 'jun', 'jul', 'avg.', 'sep.', 'okt.', 'nov.', 'dec.'], + weekdays: ['nedelja', 'ponedeljak', 'utorak', 'sreda', 'četvrtak', 'petak', 'subota'], + weekdaysShort: ['ned.', 'pon.', 'uto.', 'sre.', 'čet.', 'pet.', 'sub.'], + weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'], + longDateFormat: { + LT: 'H:mm', + LTS : 'LT:ss', + L: 'DD. MM. YYYY', + LL: 'D. MMMM YYYY', + LLL: 'D. MMMM YYYY LT', + LLLL: 'dddd, D. MMMM YYYY LT' + }, + calendar: { + sameDay: '[danas u] LT', + nextDay: '[sutra u] LT', + nextWeek: function () { + switch (this.day()) { + case 0: + return '[u] [nedelju] [u] LT'; + case 3: + return '[u] [sredu] [u] LT'; + case 6: + return '[u] [subotu] [u] LT'; + case 1: + case 2: + case 4: + case 5: + return '[u] dddd [u] LT'; + } + }, + lastDay : '[juče u] LT', + lastWeek : function () { + var lastWeekDays = [ + '[prošle] [nedelje] [u] LT', + '[prošlog] [ponedeljka] [u] LT', + '[prošlog] [utorka] [u] LT', + '[prošle] [srede] [u] LT', + '[prošlog] [četvrtka] [u] LT', + '[prošlog] [petka] [u] LT', + '[prošle] [subote] [u] LT' + ]; + return lastWeekDays[this.day()]; + }, + sameElse : 'L' + }, + relativeTime : { + future : 'za %s', + past : 'pre %s', + s : 'nekoliko sekundi', + m : translator.translate, + mm : translator.translate, + h : translator.translate, + hh : translator.translate, + d : 'dan', + dd : translator.translate, + M : 'mesec', + MM : translator.translate, + y : 'godinu', + yy : translator.translate + }, + ordinalParse: /\d{1,2}\./, + 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/bower_components/moment/src/locale/sv.js b/bower_components/moment/src/locale/sv.js new file mode 100644 index 0000000..6fc1c26 --- /dev/null +++ b/bower_components/moment/src/locale/sv.js @@ -0,0 +1,58 @@ +//! moment.js locale configuration +//! locale : swedish (sv) +//! author : Jens Alm : https://github.com/ulmus + +import moment from '../moment'; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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: '[På] dddd LT', + lastWeek: '[I] dddd[s] 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' + }, + ordinalParse: /\d{1,2}(e|a)/, + 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/bower_components/moment/src/locale/ta.js b/bower_components/moment/src/locale/ta.js new file mode 100644 index 0000000..4341c3e --- /dev/null +++ b/bower_components/moment/src/locale/ta.js @@ -0,0 +1,86 @@ +//! moment.js locale configuration +//! locale : tamil (ta) +//! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404 + +import moment from '../moment'; + +export default moment.defineLocale('ta', { + months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'), + weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'), + weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'), + weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 ஆண்டுகள்' + }, + ordinalParse: /\d{1,2}வது/, + ordinal : function (number) { + return number + 'வது'; + }, + // refer http://ta.wikipedia.org/s/1er1 + meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/, + meridiem : function (hour, minute, isLower) { + if (hour < 2) { + return ' யாமம்'; + } else if (hour < 6) { + return ' வைகறை'; // வைகறை + } else if (hour < 10) { + return ' காலை'; // காலை + } else if (hour < 14) { + return ' நண்பகல்'; // நண்பகல் + } else if (hour < 18) { + return ' எற்பாடு'; // எற்பாடு + } else if (hour < 22) { + return ' மாலை'; // மாலை + } else { + return ' யாமம்'; + } + }, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === 'யாமம்') { + return hour < 2 ? hour : hour + 12; + } else if (meridiem === 'வைகறை' || meridiem === 'காலை') { + return hour; + } else if (meridiem === 'நண்பகல்') { + return hour >= 10 ? hour : hour + 12; + } else { + return hour + 12; + } + }, + 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/bower_components/moment/src/locale/th.js b/bower_components/moment/src/locale/th.js new file mode 100644 index 0000000..2382d25 --- /dev/null +++ b/bower_components/moment/src/locale/th.js @@ -0,0 +1,56 @@ +//! moment.js locale configuration +//! locale : thai (th) +//! author : Kridsada Thanabulpong : https://github.com/sirn + +import moment from '../moment'; + +export default moment.defineLocale('th', { + months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'), + monthsShort : 'มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา'.split('_'), + weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'), + weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference + weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'), + longDateFormat : { + LT : 'H นาฬิกา m นาที', + LTS : 'LT s วินาที', + L : 'YYYY/MM/DD', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY เวลา LT', + LLLL : 'วันddddที่ D MMMM YYYY เวลา LT' + }, + meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/, + isPM: function (input) { + return input === 'หลังเที่ยง'; + }, + 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/bower_components/moment/src/locale/tl-ph.js b/bower_components/moment/src/locale/tl-ph.js new file mode 100644 index 0000000..a1b24a7 --- /dev/null +++ b/bower_components/moment/src/locale/tl-ph.js @@ -0,0 +1,53 @@ +//! moment.js locale configuration +//! locale : Tagalog/Filipino (tl-ph) +//! author : Dan Hagman + +import moment from '../moment'; + +export default moment.defineLocale('tl-ph', { + months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'), + monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'), + weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'), + weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'), + weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'MM/D/YYYY', + LL : 'MMMM D, YYYY', + LLL : 'MMMM D, YYYY LT', + LLLL : 'dddd, MMMM DD, YYYY LT' + }, + calendar : { + sameDay: '[Ngayon sa] LT', + nextDay: '[Bukas sa] LT', + nextWeek: 'dddd [sa] LT', + lastDay: '[Kahapon sa] LT', + lastWeek: 'dddd [huling linggo] LT', + sameElse: 'L' + }, + relativeTime : { + future : 'sa loob ng %s', + past : '%s ang nakalipas', + s : 'ilang segundo', + m : 'isang minuto', + mm : '%d minuto', + h : 'isang oras', + hh : '%d oras', + d : 'isang araw', + dd : '%d araw', + M : 'isang buwan', + MM : '%d buwan', + y : 'isang taon', + yy : '%d taon' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + 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/bower_components/moment/src/locale/tr.js b/bower_components/moment/src/locale/tr.js new file mode 100644 index 0000000..78f2b69 --- /dev/null +++ b/bower_components/moment/src/locale/tr.js @@ -0,0 +1,81 @@ +//! moment.js locale configuration +//! locale : turkish (tr) +//! authors : Erhan Gundogan : https://github.com/erhangundogan, +//! Burak Yiğit Kaya: https://github.com/BYK + +import moment from '../moment'; + +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ı' +}; + +export default moment.defineLocale('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', + LTS : 'LT:ss', + 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' + }, + ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/, + 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/bower_components/moment/src/locale/tzm-latn.js b/bower_components/moment/src/locale/tzm-latn.js new file mode 100644 index 0000000..153e51f --- /dev/null +++ b/bower_components/moment/src/locale/tzm-latn.js @@ -0,0 +1,49 @@ +//! moment.js locale configuration +//! locale : Morocco Central Atlas Tamaziɣt in Latin (tzm-latn) +//! author : Abdel Said : https://github.com/abdelsaid + +import moment from '../moment'; + +export default moment.defineLocale('tzm-latn', { + 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', + LTS : 'LT:ss', + 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/bower_components/moment/src/locale/tzm.js b/bower_components/moment/src/locale/tzm.js new file mode 100644 index 0000000..b53adb0 --- /dev/null +++ b/bower_components/moment/src/locale/tzm.js @@ -0,0 +1,49 @@ +//! moment.js locale configuration +//! locale : Morocco Central Atlas Tamaziɣt (tzm) +//! author : Abdel Said : https://github.com/abdelsaid + +import moment from '../moment'; + +export default moment.defineLocale('tzm', { + months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'), + weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS: 'LT:ss', + 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/bower_components/moment/src/locale/uk.js b/bower_components/moment/src/locale/uk.js new file mode 100644 index 0000000..6fd7a1e --- /dev/null +++ b/bower_components/moment/src/locale/uk.js @@ -0,0 +1,144 @@ +//! moment.js locale configuration +//! locale : ukrainian (uk) +//! author : zemlanin : https://github.com/zemlanin +//! Author : Menelion Elensúle : https://github.com/Oire + +import moment from '../moment'; + +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'; + }; +} + +export default moment.defineLocale('uk', { + months : monthsCaseReplace, + monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'), + weekdays : weekdaysCaseReplace, + weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + 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 + }, + // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason + meridiemParse: /ночі|ранку|дня|вечора/, + isPM: function (input) { + return /^(дня|вечора)$/.test(input); + }, + meridiem : function (hour, minute, isLower) { + if (hour < 4) { + return 'ночі'; + } else if (hour < 12) { + return 'ранку'; + } else if (hour < 17) { + return 'дня'; + } else { + return 'вечора'; + } + }, + ordinalParse: /\d{1,2}-(й|го)/, + 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/bower_components/moment/src/locale/uz.js b/bower_components/moment/src/locale/uz.js new file mode 100644 index 0000000..3732bfd --- /dev/null +++ b/bower_components/moment/src/locale/uz.js @@ -0,0 +1,49 @@ +//! moment.js locale configuration +//! locale : uzbek (uz) +//! author : Sardor Muminov : https://github.com/muminoff + +import moment from '../moment'; + +export default moment.defineLocale('uz', { + months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'), + monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'), + weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'), + weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'), + weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM YYYY', + LLL : 'D MMMM YYYY LT', + LLLL : 'D MMMM YYYY, dddd 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 : 1, // Monday is the first day of the week. + doy : 7 // The week that contains Jan 4th is the first week of the year. + } +}); + diff --git a/bower_components/moment/src/locale/vi.js b/bower_components/moment/src/locale/vi.js new file mode 100644 index 0000000..18ca9f3 --- /dev/null +++ b/bower_components/moment/src/locale/vi.js @@ -0,0 +1,57 @@ +//! moment.js locale configuration +//! locale : vietnamese (vi) +//! author : Bang Nguyen : https://github.com/bangnk + +import moment from '../moment'; + +export default moment.defineLocale('vi', { + months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'), + monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'), + weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'), + weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'), + longDateFormat : { + LT : 'HH:mm', + LTS : 'LT:ss', + L : 'DD/MM/YYYY', + LL : 'D MMMM [năm] YYYY', + LLL : 'D MMMM [năm] YYYY LT', + LLLL : 'dddd, D MMMM [năm] YYYY LT', + l : 'DD/M/YYYY', + ll : 'D MMM YYYY', + lll : 'D MMM YYYY LT', + llll : 'ddd, D MMM YYYY LT' + }, + calendar : { + sameDay: '[Hôm nay lúc] LT', + nextDay: '[Ngày mai lúc] LT', + nextWeek: 'dddd [tuần tới lúc] LT', + lastDay: '[Hôm qua lúc] LT', + lastWeek: 'dddd [tuần rồi lúc] LT', + sameElse: 'L' + }, + relativeTime : { + future : '%s tới', + past : '%s trước', + s : 'vài giây', + m : 'một phút', + mm : '%d phút', + h : 'một giờ', + hh : '%d giờ', + d : 'một ngày', + dd : '%d ngày', + M : 'một tháng', + MM : '%d tháng', + y : 'một năm', + yy : '%d năm' + }, + ordinalParse: /\d{1,2}/, + ordinal : function (number) { + return number; + }, + 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/bower_components/moment/src/locale/zh-cn.js b/bower_components/moment/src/locale/zh-cn.js new file mode 100644 index 0000000..dfc0d04 --- /dev/null +++ b/bower_components/moment/src/locale/zh-cn.js @@ -0,0 +1,118 @@ +//! moment.js locale configuration +//! locale : chinese (zh-cn) +//! author : suupic : https://github.com/suupic +//! author : Zeno Zeng : https://github.com/zenozeng + +import moment from '../moment'; + +export default moment.defineLocale('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分', + LTS : 'Ah点m分s秒', + L : 'YYYY-MM-DD', + LL : 'YYYY年MMMD日', + LLL : 'YYYY年MMMD日LT', + LLLL : 'YYYY年MMMD日ddddLT', + l : 'YYYY-MM-DD', + ll : 'YYYY年MMMD日', + lll : 'YYYY年MMMD日LT', + llll : 'YYYY年MMMD日ddddLT' + }, + meridiemParse: /凌晨|早上|上午|中午|下午|晚上/, + meridiemHour: function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '凌晨' || meridiem === '早上' || + meridiem === '上午') { + return hour; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } else { + // '中午' + return hour >= 11 ? hour : hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 600) { + return '凌晨'; + } else if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : function () { + return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT'; + }, + nextDay : function () { + return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT'; + }, + lastDay : function () { + return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT'; + }, + nextWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment().startOf('week'); + prefix = this.unix() - startOfWeek.unix() >= 7 * 24 * 3600 ? '[下]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + lastWeek : function () { + var startOfWeek, prefix; + startOfWeek = moment().startOf('week'); + prefix = this.unix() < startOfWeek.unix() ? '[上]' : '[本]'; + return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm'; + }, + sameElse : 'LL' + }, + ordinalParse: /\d{1,2}(日|月|周)/, + 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 年' + }, + week : { + // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效 + 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/bower_components/moment/src/locale/zh-tw.js b/bower_components/moment/src/locale/zh-tw.js new file mode 100644 index 0000000..918700a --- /dev/null +++ b/bower_components/moment/src/locale/zh-tw.js @@ -0,0 +1,91 @@ +//! moment.js locale configuration +//! locale : traditional chinese (zh-tw) +//! author : Ben : https://github.com/ben-lin + +import moment from '../moment'; + +export default moment.defineLocale('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分', + LTS : 'Ah點m分s秒', + 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' + }, + meridiemParse: /早上|上午|中午|下午|晚上/, + meridiemHour : function (hour, meridiem) { + if (hour === 12) { + hour = 0; + } + if (meridiem === '早上' || meridiem === '上午') { + return hour; + } else if (meridiem === '中午') { + return hour >= 11 ? hour : hour + 12; + } else if (meridiem === '下午' || meridiem === '晚上') { + return hour + 12; + } + }, + meridiem : function (hour, minute, isLower) { + var hm = hour * 100 + minute; + if (hm < 900) { + return '早上'; + } else if (hm < 1130) { + return '上午'; + } else if (hm < 1230) { + return '中午'; + } else if (hm < 1800) { + return '下午'; + } else { + return '晚上'; + } + }, + calendar : { + sameDay : '[今天]LT', + nextDay : '[明天]LT', + nextWeek : '[下]ddddLT', + lastDay : '[昨天]LT', + lastWeek : '[上]ddddLT', + sameElse : 'L' + }, + ordinalParse: /\d{1,2}(日|月|週)/, + 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/bower_components/moment/src/moment.js b/bower_components/moment/src/moment.js new file mode 100644 index 0000000..4407eb9 --- /dev/null +++ b/bower_components/moment/src/moment.js @@ -0,0 +1,68 @@ +//! moment.js +//! version : 2.10.3 +//! authors : Tim Wood, Iskren Chernev, Moment.js contributors +//! license : MIT +//! momentjs.com + +import { hooks as moment, setHookCallback } from './lib/utils/hooks'; + +moment.version = '2.10.3'; + +import { + min, + max, + isMoment, + momentPrototype as fn, + createUTC as utc, + createUnix as unix, + createLocal as local, + createInvalid as invalid, + createInZone as parseZone +} from './lib/moment/moment'; + +import { + defineLocale, + getSetGlobalLocale as locale, + getLocale as localeData, + listMonths as months, + listMonthsShort as monthsShort, + listWeekdays as weekdays, + listWeekdaysMin as weekdaysMin, + listWeekdaysShort as weekdaysShort +} from './lib/locale/locale'; + +import { + isDuration, + createDuration as duration, + getSetRelativeTimeThreshold as relativeTimeThreshold +} from './lib/duration/duration'; + +import { normalizeUnits } from './lib/units/units'; + +import isDate from './lib/utils/is-date'; + +setHookCallback(local); + +moment.fn = fn; +moment.min = min; +moment.max = max; +moment.utc = utc; +moment.unix = unix; +moment.months = months; +moment.isDate = isDate; +moment.locale = locale; +moment.invalid = invalid; +moment.duration = duration; +moment.isMoment = isMoment; +moment.weekdays = weekdays; +moment.parseZone = parseZone; +moment.localeData = localeData; +moment.isDuration = isDuration; +moment.monthsShort = monthsShort; +moment.weekdaysMin = weekdaysMin; +moment.defineLocale = defineLocale; +moment.weekdaysShort = weekdaysShort; +moment.normalizeUnits = normalizeUnits; +moment.relativeTimeThreshold = relativeTimeThreshold; + +export default moment; diff --git a/bower_components/moment/templates/amd-named.js b/bower_components/moment/templates/amd-named.js new file mode 100644 index 0000000..7610456 --- /dev/null +++ b/bower_components/moment/templates/amd-named.js @@ -0,0 +1,7 @@ +/*global define:false*/ + +import moment from "./moment"; + +define("moment", [], function () { + return moment; +}); diff --git a/bower_components/moment/templates/amd.js b/bower_components/moment/templates/amd.js new file mode 100644 index 0000000..847bcef --- /dev/null +++ b/bower_components/moment/templates/amd.js @@ -0,0 +1,7 @@ +/*global define:false*/ + +import moment from "./moment"; + +define([], function () { + return moment; +}); diff --git a/bower_components/moment/templates/globals.js b/bower_components/moment/templates/globals.js new file mode 100644 index 0000000..5ac160f --- /dev/null +++ b/bower_components/moment/templates/globals.js @@ -0,0 +1,5 @@ +/*global window:false*/ + +import moment from "./moment"; + +window.moment = moment; diff --git a/bower_components/moment/templates/locale-header.js b/bower_components/moment/templates/locale-header.js new file mode 100644 index 0000000..f304506 --- /dev/null +++ b/bower_components/moment/templates/locale-header.js @@ -0,0 +1,5 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) : + typeof define === 'function' && define.amd ? define(['moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; diff --git a/bower_components/moment/templates/test-header.js b/bower_components/moment/templates/test-header.js new file mode 100644 index 0000000..38940c3 --- /dev/null +++ b/bower_components/moment/templates/test-header.js @@ -0,0 +1,5 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../../moment')) : + typeof define === 'function' && define.amd ? define(['../../moment'], factory) : + factory(global.moment) +}(this, function (moment) { 'use strict'; diff --git a/docs/architecture/nikola-architecture-draw-io.png b/docs/architecture/nikola-architecture-draw-io.png Binary files differnew file mode 100644 index 0000000..0e0f391 --- /dev/null +++ b/docs/architecture/nikola-architecture-draw-io.png diff --git a/docs/architecture/nikola-architecture-draw-io.svg b/docs/architecture/nikola-architecture-draw-io.svg new file mode 100644 index 0000000..9470c32 --- /dev/null +++ b/docs/architecture/nikola-architecture-draw-io.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="2556px" height="548px" version="1.1"><defs><linearGradient x1="0%" y1="0%" x2="0%" y2="100%" id="mx-gradient-e1d5e7-1-8c6c9c-1-s-0"><stop offset="0%" style="stop-color:#E1D5E7"/><stop offset="100%" style="stop-color:#8C6C9C"/></linearGradient><linearGradient x1="0%" y1="0%" x2="0%" y2="100%" id="mx-gradient-ffffff-0.9-ffffff-0.1-s-0"><stop offset="0%" style="stop-color:#ffffff;stop-opacity:0.9"/><stop offset="100%" style="stop-color:#ffffff;stop-opacity:0.1"/></linearGradient><linearGradient x1="0%" y1="0%" x2="0%" y2="100%" id="mx-gradient-dae8fc-1-7ea6e0-1-s-0"><stop offset="0%" style="stop-color:#DAE8FC"/><stop offset="100%" style="stop-color:#7EA6E0"/></linearGradient><linearGradient x1="0%" y1="100%" x2="0%" y2="0%" id="mx-gradient-ffffff-1-ffff33-1-s-0"><stop offset="0%" style="stop-color:#FFFF33"/><stop offset="100%" style="stop-color:#ffffff"/></linearGradient><linearGradient x1="0%" y1="0%" x2="0%" y2="100%" id="mx-gradient-f8cecc-1-66ff66-1-s-0"><stop offset="0%" style="stop-color:#F8CECC"/><stop offset="100%" style="stop-color:#66FF66"/></linearGradient><linearGradient x1="0%" y1="0%" x2="0%" y2="100%" id="mx-gradient-ffffff-1-ff66b3-1-s-0"><stop offset="0%" style="stop-color:#ffffff"/><stop offset="100%" style="stop-color:#FF66B3"/></linearGradient><linearGradient x1="0%" y1="0%" x2="0%" y2="100%" id="mx-gradient-ffffff-1-ff9933-1-s-0"><stop offset="0%" style="stop-color:#ffffff"/><stop offset="100%" style="stop-color:#FF9933"/></linearGradient><linearGradient x1="0%" y1="0%" x2="0%" y2="100%" id="mx-gradient-ffffff-1-66ff66-1-s-0"><stop offset="0%" style="stop-color:#ffffff"/><stop offset="100%" style="stop-color:#66FF66"/></linearGradient><linearGradient x1="0%" y1="0%" x2="0%" y2="100%" id="mx-gradient-ffffff-1-66ffff-1-s-0"><stop offset="0%" style="stop-color:#ffffff"/><stop offset="100%" style="stop-color:#66FFFF"/></linearGradient><linearGradient x1="0%" y1="0%" x2="0%" y2="100%" id="mx-gradient-ffffff-1-ffff66-1-s-0"><stop offset="0%" style="stop-color:#ffffff"/><stop offset="100%" style="stop-color:#FFFF66"/></linearGradient></defs><g transform="translate(0.5,0.5)"><rect x="2.58" y="425.61" width="1530" height="56" fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1"/><rect x="2.58" y="425.61" width="1530" height="56" fill="url(#mx-gradient-e1d5e7-1-8c6c9c-1-s-0)" stroke="#000000" pointer-events="none"/><path d="M 1.58 424.61 L 1.58 448.01 Q 767.58 464.81 1533.58 448.01 L 1533.58 424.61 Z" fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none" pointer-events="none"/><g transform="translate(712,415)"><switch><foreignObject pointer-events="all" width="109" height="78" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 109px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><h1><font style="font-size: 35px ; font-weight: normal">Yapsy</font></h1></div></div></foreignObject><text x="55" y="45" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1550.58" y="425.61" width="1001" height="60" fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1"/><rect x="1550.58" y="425.61" width="1001" height="60" fill="url(#mx-gradient-dae8fc-1-7ea6e0-1-s-0)" stroke="#000000" pointer-events="none"/><path d="M 1549.58 424.61 L 1549.58 449.61 Q 2051.08 467.61 2552.58 449.61 L 2552.58 424.61 Z" fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none" pointer-events="none"/><g transform="translate(2019,420)"><switch><foreignObject pointer-events="all" width="62" height="71" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 62px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><h2><font style="font-size: 31px ; font-weight: normal">doit</font></h2></div></div></foreignObject><text x="31" y="42" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="2.58" y="377.61" width="1529" height="38" fill="url(#mx-gradient-ffffff-1-ffff33-1-s-0)" stroke="#000000" pointer-events="none"/><g transform="translate(730,371)"><switch><foreignObject pointer-events="all" width="72" height="52" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 72px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><h3><font style="font-size: 18px">IPlugin</font></h3></div></div></foreignObject><text x="36" y="32" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="3.58" y="287.61" width="1526" height="79" fill="#d0d0d0" stroke="#d0d0d0" transform="translate(2,3)" opacity="1"/><rect x="3.58" y="287.61" width="1526" height="79" fill="url(#mx-gradient-f8cecc-1-66ff66-1-s-0)" stroke="#000000" pointer-events="none"/><path d="M 2.58 286.61 L 2.58 319.21 Q 766.58 342.91 1530.58 319.21 L 1530.58 286.61 Z" fill="url(#mx-gradient-ffffff-0.9-ffffff-0.1-s-0)" stroke="none" pointer-events="none"/><rect x="162.58" y="297.61" width="149" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(215,304)"><switch><foreignObject pointer-events="all" width="42" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 42px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">Task</font></b></div></div></foreignObject><text x="21" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="464.58" y="297.61" width="149" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(480,304)"><switch><foreignObject pointer-events="all" width="116" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 116px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">TemplateSystem</font></b></div></div></foreignObject><text x="58" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1370.58" y="297.61" width="149" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(1398,304)"><switch><foreignObject pointer-events="all" width="92" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 92px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">ConfigPlugin</font></b></div></div></foreignObject><text x="46" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1068.58" y="297.61" width="149" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(1073,304)"><switch><foreignObject pointer-events="all" width="138" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 138px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">MarkdownExtension</font></b></div></div></foreignObject><text x="69" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="914.58" y="297.61" width="149" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(938,304)"><switch><foreignObject pointer-events="all" width="100" height="17" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 100px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><span style="line-height: 13.8599996566772px"><b><font style="font-size: 13px">TaskMultiplier</font></b></span></div></div></foreignObject><text x="50" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="766.58" y="297.61" width="143" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(786,304)"><switch><foreignObject pointer-events="all" width="102" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 102px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">RestExtension</font></b></div></div></foreignObject><text x="51" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1222.58" y="297.61" width="143" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(1243,304)"><switch><foreignObject pointer-events="all" width="100" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 100px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">SignalHandler</font></b></div></div></foreignObject><text x="50" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="14.58" y="297.61" width="143" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(47,304)"><switch><foreignObject pointer-events="all" width="76" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 76px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">Command</font></b></div></div></foreignObject><text x="38" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="316.58" y="297.61" width="143" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(353,304)"><switch><foreignObject pointer-events="all" width="68" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 68px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">LateTask</font></b></div></div></foreignObject><text x="34" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="618.58" y="297.61" width="143" height="30" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(639,304)"><switch><foreignObject pointer-events="all" width="100" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 100px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">PageCompiler</font></b></div></div></foreignObject><text x="50" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="615.58" y="334.61" width="295" height="25" fill="none" stroke="none" pointer-events="none"/><g transform="translate(703,339)"><switch><foreignObject pointer-events="all" width="121" height="19" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 21px; max-width: 291px; width: 121px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 14px">Plugin Categories</font></b></div></div></foreignObject><text x="61" y="16" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="14.58" y="109.61" width="143" height="169" fill="none" stroke="#000000" pointer-events="none"/><g transform="translate(79,186)"><switch><foreignObject pointer-events="all" width="12" height="17" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 12px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><div style="text-align: left"><br /></div></div></div></foreignObject><text x="6" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="23.58" y="118.61" width="129" height="22" fill="none" stroke="none" pointer-events="none"/><g transform="translate(52,122)"><switch><foreignObject pointer-events="all" width="73" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 18px; max-width: 125px; width: 73px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">Commands</font></b><div><br /></div></div></div></foreignObject><text x="37" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="29.58" y="140.61" width="114" height="129" fill="none" stroke="none" pointer-events="none"/><g transform="translate(51,145)"><switch><foreignObject pointer-events="all" width="72" height="122" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 125px; max-width: 110px; width: 72px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">init<div>install_theme</div><div>new_post</div><div>new_page</div><div>deploy</div><div>serve</div><div>...</div><div><br /></div></div></div></foreignObject><text x="36" y="67" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="163.58" y="110.61" width="143" height="169" fill="none" stroke="#000000" pointer-events="none"/><g transform="translate(228,187)"><switch><foreignObject pointer-events="all" width="12" height="17" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 12px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><div style="text-align: left"><br /></div></div></div></foreignObject><text x="6" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="174.58" y="118.61" width="129" height="22" fill="none" stroke="none" pointer-events="none"/><g transform="translate(220,122)"><switch><foreignObject pointer-events="all" width="39" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 18px; max-width: 125px; width: 39px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">Tasks</font></b></div></div></foreignObject><text x="20" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="181.58" y="141.61" width="114" height="129" fill="none" stroke="none" pointer-events="none"/><g transform="translate(216,146)"><switch><foreignObject pointer-events="all" width="46" height="122" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 125px; max-width: 110px; width: 46px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><div>archives</div><div>galleries</div><div>indexes</div><div>pages</div><div>posts</div><div>rss</div><div>tags</div><div>...</div></div></div></foreignObject><text x="23" y="67" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="482.58" y="169.61" width="114" height="55" fill="none" stroke="none" pointer-events="none"/><g transform="translate(524,182)"><switch><foreignObject pointer-events="all" width="32" height="32" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 51px; max-width: 110px; width: 32px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;">jinja<div>mako</div></div></div></foreignObject><text x="16" y="22" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="467.58" y="109.61" width="143" height="169" fill="none" stroke="#000000" pointer-events="none"/><g transform="translate(532,186)"><switch><foreignObject pointer-events="all" width="12" height="17" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 12px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><div style="text-align: left"><br /></div></div></div></foreignObject><text x="6" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="477.58" y="118.61" width="129" height="22" fill="none" stroke="none" pointer-events="none"/><g transform="translate(484,122)"><switch><foreignObject pointer-events="all" width="117" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 18px; max-width: 125px; width: 117px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">Template Systems</font></b></div></div></foreignObject><text x="59" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="619.58" y="109.61" width="143" height="169" fill="none" stroke="#000000" pointer-events="none"/><g transform="translate(656,156)"><switch><foreignObject pointer-events="all" width="68" height="77" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 68px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><div style="text-align: left">ipynb</div><div style="text-align: left">markdown</div><div style="text-align: left">rest</div><div style="text-align: left">php</div><div style="text-align: left">pandoc</div></div></div></foreignObject><text x="34" y="45" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="626.58" y="119.61" width="129" height="22" fill="none" stroke="none" pointer-events="none"/><g transform="translate(641,123)"><switch><foreignObject pointer-events="all" width="101" height="18" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 18px; max-width: 125px; width: 101px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 13px">Page Compilers</font></b></div></div></foreignObject><text x="51" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1879.58" y="274.61" width="544" height="85" fill="none" stroke="#000000" pointer-events="none"/><g transform="translate(2145,309)"><switch><foreignObject pointer-events="all" width="12" height="17" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 12px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><br /></div></div></foreignObject><text x="6" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1550.58" y="378.61" width="320" height="37" fill="url(#mx-gradient-ffffff-1-ff66b3-1-s-0)" stroke="#000000" pointer-events="none"/><g transform="translate(1664,388)"><switch><foreignObject pointer-events="all" width="91" height="19" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 91px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><font style="font-size: 14px"><b>TaskLoader</b></font></div></div></foreignObject><text x="46" y="16" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1550.58" y="333.61" width="320" height="37" fill="url(#mx-gradient-ffffff-1-ff9933-1-s-0)" stroke="#000000" pointer-events="none"/><g transform="translate(1643,343)"><switch><foreignObject pointer-events="all" width="133" height="19" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 133px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><font style="font-size: 14px"><b>NikolaTaskLoader</b></font></div></div></foreignObject><text x="67" y="16" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1887.58" y="286.61" width="128" height="32" fill="url(#mx-gradient-ffffff-1-ff9933-1-s-0)" stroke="#000000" pointer-events="none"/><g transform="translate(1931,293)"><switch><foreignObject pointer-events="all" width="39" height="19" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 39px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 14px">Run</font></b></div></div></foreignObject><text x="20" y="16" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="2288.58" y="286.61" width="128" height="32" fill="url(#mx-gradient-ffffff-1-ffff33-1-s-0)" stroke="#000000" pointer-events="none"/><g transform="translate(2330,293)"><switch><foreignObject pointer-events="all" width="43" height="19" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 43px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 14px">Auto</font></b></div></div></foreignObject><text x="22" y="16" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="2155.58" y="286.61" width="128" height="32" fill="url(#mx-gradient-ffffff-1-66ff66-1-s-0)" stroke="#000000" pointer-events="none"/><g transform="translate(2197,293)"><switch><foreignObject pointer-events="all" width="43" height="19" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 43px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 14px">Help</font></b></div></div></foreignObject><text x="22" y="16" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="2022.58" y="286.61" width="128" height="32" fill="url(#mx-gradient-ffffff-1-66ffff-1-s-0)" stroke="#000000" pointer-events="none"/><g transform="translate(2060,293)"><switch><foreignObject pointer-events="all" width="51" height="19" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 51px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 14px">Clean</font></b></div></div></foreignObject><text x="26" y="16" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1890.58" y="314.61" width="525" height="40" fill="none" stroke="none" pointer-events="none"/><g transform="translate(2075,318)"><switch><foreignObject pointer-events="all" width="157" height="36" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 36px; max-width: 521px; width: 157px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><h3><b><font style="font-size: 16px">doit Sub Commands</font></b></h3><div><br /></div></div></div></foreignObject><text x="79" y="24" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1879.58" y="186.61" width="544" height="79" fill="none" stroke="#000000" pointer-events="none"/><g transform="translate(2145,218)"><switch><foreignObject pointer-events="all" width="12" height="17" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 12px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><br /></div></div></foreignObject><text x="6" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1889.58" y="177.61" width="525" height="40" fill="none" stroke="none" pointer-events="none"/><g transform="translate(2064,181)"><switch><foreignObject pointer-events="all" width="177" height="36" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 36px; max-width: 521px; width: 177px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><h3><b><font style="font-size: 16px">Nikola Sub Commands</font></b></h3><div><br /></div></div></div></foreignObject><text x="89" y="24" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1887.58" y="225.61" width="128" height="32" fill="url(#mx-gradient-ffffff-1-ff9933-1-s-0)" stroke="#000000" pointer-events="none"/><g transform="translate(1927,232)"><switch><foreignObject pointer-events="all" width="47" height="19" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 47px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 14px">Build</font></b></div></div></foreignObject><text x="24" y="16" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="2021.58" y="225.61" width="128" height="32" fill="url(#mx-gradient-ffffff-1-66ffff-1-s-0)" stroke="#000000" pointer-events="none"/><g transform="translate(2059,232)"><switch><foreignObject pointer-events="all" width="51" height="19" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 51px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 14px">Clean</font></b></div></div></foreignObject><text x="26" y="16" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="2155.58" y="225.61" width="128" height="32" fill="url(#mx-gradient-ffffff-1-66ff66-1-s-0)" stroke="#000000" pointer-events="none"/><g transform="translate(2197,232)"><switch><foreignObject pointer-events="all" width="43" height="19" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 43px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 14px">Help</font></b></div></div></foreignObject><text x="22" y="16" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="2288.58" y="225.61" width="128" height="32" fill="url(#mx-gradient-ffffff-1-ffff66-1-s-0)" stroke="#000000" pointer-events="none"/><g transform="translate(2330,232)"><switch><foreignObject pointer-events="all" width="43" height="19" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 43px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 14px">Auto</font></b></div></div></foreignObject><text x="22" y="16" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1550.58" y="150.61" width="321" height="138" fill="none" stroke="#000000" pointer-events="none"/><g transform="translate(1704,211)"><switch><foreignObject pointer-events="all" width="12" height="17" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 12px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><br /></div></div></foreignObject><text x="6" y="15" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1593.58" y="122.61" width="232" height="59" fill="none" stroke="none" pointer-events="none"/><g transform="translate(1671,130)"><switch><foreignObject pointer-events="all" width="78" height="47" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; overflow: hidden; max-height: 55px; max-width: 228px; width: 78px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><br /></b><div><div><b><br /></b></div><div><b>default_tasks</b></div></div></div></div></foreignObject><text x="39" y="30" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><path d="M 1710.76 122.88 L 1710.76 122.88" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><path d="M 1710.76 122.88 L 1710.76 122.88 L 1710.76 122.88 L 1710.76 122.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><rect x="1552.58" y="296.61" width="318" height="28" fill="none" stroke="#000000" pointer-events="none"/><g transform="translate(1668,301)"><switch><foreignObject pointer-events="all" width="85" height="19" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 85px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 14px">load_tasks</font></b></div></div></foreignObject><text x="43" y="16" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1561.58" y="189.61" width="138" height="80" fill="none" stroke="#000000" pointer-events="none"/><g transform="translate(1562,206)"><switch><foreignObject pointer-events="all" width="135" height="47" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 133px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b>render_site</b><div>Group of tasks to render the site<br /></div></div></div></foreignObject><text x="68" y="30" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1713.58" y="190.61" width="141" height="79" fill="none" stroke="#000000" pointer-events="none"/><g transform="translate(1714,199)"><switch><foreignObject pointer-events="all" width="138" height="62" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 136px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><div><b>post_render</b></div>Group of tasks to be executed after site is rendered.</div></div></foreignObject><text x="69" y="37" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><path d="M 1950.15 225.91 L 1950.15 41.61 L 1710.76 41.61 L 1710.76 143.78" fill="none" stroke="#d0d0d0" stroke-miterlimit="10" stroke-dasharray="3 3" transform="translate(2,3)" opacity="1"/><path d="M 1950.15 225.91 L 1950.15 41.61 L 1710.76 41.61 L 1710.76 143.78" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="none"/><path d="M 1710.76 149.03 L 1707.26 142.03 L 1710.76 143.78 L 1714.26 142.03 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(1771,13)"><switch><foreignObject pointer-events="all" width="92" height="73" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;"><h2><b><font color="#cc0000" style="font-size: 21px">executes</font></b></h2><div><br /></div></div></div></foreignObject><text x="46" y="43" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><path d="M 1628.94 186.52 L 1628.94 32.61 L 235 32.61 L 235 104.39" fill="none" stroke="#d0d0d0" stroke-miterlimit="10" stroke-dasharray="3 3" transform="translate(2,3)" opacity="1"/><path d="M 1628.94 186.52 L 1628.94 32.61 L 235 32.61 L 235 104.39" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="none"/><path d="M 235 109.64 L 231.5 102.64 L 235 104.39 L 238.5 102.64 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(861,3)"><switch><foreignObject pointer-events="all" width="193" height="60" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;"><h4><font style="font-size: 21px" color="#cc0000">implemented using</font></h4></div></div></foreignObject><text x="97" y="36" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><path d="M 1783.48 189.55 L 1784.08 82.61 L 388.08 82.61 L 389.5 292.27" fill="none" stroke="#d0d0d0" stroke-miterlimit="10" stroke-dasharray="3 3" transform="translate(2,3)" opacity="1"/><path d="M 1783.48 189.55 L 1784.08 82.61 L 388.08 82.61 L 389.5 292.27" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="none"/><path d="M 389.54 297.52 L 385.99 290.54 L 389.5 292.27 L 392.99 290.49 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(1007,53)"><switch><foreignObject pointer-events="all" width="193" height="60" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;"><h4><font style="font-size: 21px" color="#cc0000">implemented using</font></h4></div></div></foreignObject><text x="97" y="36" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="2429.58" y="370.61" width="120" height="49" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(2449,384)"><switch><foreignObject pointer-events="all" width="79" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 79px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 16px">DoitMain</font></b></div></div></foreignObject><text x="40" y="17" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="2429.58" y="310.61" width="120" height="49" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(2443,324)"><switch><foreignObject pointer-events="all" width="91" height="22" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 91px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 16px">DoitNikola</font></b></div></div></foreignObject><text x="46" y="17" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><rect x="1879.58" y="368.61" width="543" height="51" fill="#ffffff" stroke="#000000" pointer-events="none"/><g transform="translate(2100,382)"><switch><foreignObject pointer-events="all" width="100" height="24" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; width: 100px; white-space: normal; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;"><b><font style="font-size: 18px">Command</font></b></div></div></foreignObject><text x="50" y="18" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g><path d="M 86.52 268.33 L 86.52 533.61 L 2150.15 533.61 L 2150.15 426.22" fill="none" stroke="#000000" stroke-miterlimit="10" stroke-dasharray="3 3" pointer-events="none"/><path d="M 2150.15 420.97 L 2153.65 427.97 L 2150.15 426.22 L 2146.65 427.97 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="none"/><g transform="translate(1051,521)"><switch><foreignObject pointer-events="all" width="193" height="28" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; font-size: 12px; font-family: Helvetica; color: rgb(0, 0, 0); line-height: 1.26; vertical-align: top; white-space: nowrap; text-align: center;"><div xmlns="http://www.w3.org/1999/xhtml" style="display:inline-block;text-align:inherit;text-decoration:inherit;background-color:#ffffff;"><font style="font-size: 21px" color="#cc0000"><b>implemented using</b></font></div></div></foreignObject><text x="97" y="20" fill="#000000" text-anchor="middle" font-size="12px" font-family="Helvetica">[Not supported by viewer]</text></switch></g></g></svg>
\ No newline at end of file diff --git a/docs/architecture/nikola-architecture-draw-io.xml b/docs/architecture/nikola-architecture-draw-io.xml new file mode 100644 index 0000000..d5aeec7 --- /dev/null +++ b/docs/architecture/nikola-architecture-draw-io.xml @@ -0,0 +1 @@ +<mxfile type="device"><diagram>7V1bc6M6Ev41eXQKTMD24yQzmdmqM1tTJ6d2d55SxMi2TjB4Aecyv/60oNuWhHCwudjJ2C82QjSgr29qtdoXzs3y5Wvirxbf44CFF0MreLlwPl8Mh0PXHV26Y/glGl+LRtv1rEvPLhrnCQ+wedtwx38xbLSwdc0DliodszgOM75SG6dxFLFpprTN4lC9xcqfE/ltw93UD8ut/+VBtsB3GVv4MOLEN8bnC7zP5kSavRKNgM38dZgN8iY4J04vfaKV93e+wMAlcQxUxK/lyw0LxeDRgBREbyvObh4yYRE+x+4LnOKCJz9c4zNeDL0QLr1eAC1vLn5RyywGmvL7eP9fi+fMTwzSHJ5P0MFxVy/wlV8J4wznnnFcxNkoTpY+PAJdTHf56a/SV7oVPHBxN/UJoFl+LG10nxc8Y3crfyqOn4HzxFtkyxCObPi5Wicr0fU6zZL4kd3EYZzkFzpW/ikPHY7mE0syhrybN+FQfmXxkmUJPLRFZ4kzkamvHDx+3nKM7VLjQuIW1yvafOTc+Yb2Fjz4gfiZsbyqxlL8OgxL+xAsg5gL7N6CUnqq/aB8yN+wSyA90k+7kLQsJCwj6WHHJkiOqpEEgT0MSXsskNSR+tePcD3nUQ2wpBvvB9aMh6GE0S18HAfa54kfcIBIOjfLP9K5zzwBxc3jCM4Ds4mR71F8nTHqaEV8h5My6A5ySxPQkYQC+n4jnTAgZRpXz7u99byOxw4vwbEbToxjh2pOHrsRjmeTsSPgDBLzcLDAOCaB+ctPH9+WFumm+0HYAhLDkcbFlgGJKxMTt6C5iAt6AIItV6EPY/maZmx52pC4I4TgKJC4fUFyE0czPq9rUY4JiH01Uu17v4hU2/eWEfnuJ49B/Bx9eclYlAo7etqw2CM0EEeBxWSBi3FJVz4MnQGFkEdsQA9S4HA5difw8VzPG42GJlQ6NE3fYXrJVyFnyV5Ib9qKFz0eA1jk9RyDAYwuWCdQ/cnS7J3I5HiE88qdiGAcoXVEEOnuEbnj88gPv/lREO4pO/0LiUNDewxIiEYf7sRyCXicOBi1FFZXWPTmbf8BnvbpT32uKAZ2FDDwXt2D8QNCzSAcK37yqmpEE/6jAFId3D4ckCsjIDjlsW5ATOZxwmFVogEuMLh5rG8LhRq3ieJIhD/lwBo2+SGYMTicAmTAG861gIrDIsYnPLHkARg4OGHCPobeszB+hpYF9GNwQTtMgEAQEzho1SUmGE5wliozwRDbGjFBtQcR8Ccj5GL4BziSAvOQzQR+VU68EEEd25x083Apolod0Wvfftk2qtC3JNT2WojbXfXtTOwnlxKfNAT9g4m0TZ4HcQ2JuMw1pkA5cVsjpil7PTzaLjhJMPAozfwwvM8WbMmqkCpdFbHn+1WcyitYNS4Qy8d1LwjYKozlxc7d3VOWPNUnfnl5WbvvmZ+JnzEkR/x8haZH5mfSjIoWJCZvxNDVnuPZRuUrGpq2oZB2PzaqCzeyMoB3dhwl3Gn99ShWpjqdQpIcP5ku+JPi7u/WuHOwR0ybIOy+gkcBe9mjv7BEe/QGQ1e/d5LW75v58/qddxitj87jyL8by4Masx/LU54d/c2jv30DQkv/Mf49IXInarjVpoj4WxC5Lcxf3eoQ39k3yJfWcZCPMn91e4v5UboDdCgyHs6OgsQEY40J+nQU3Gr/sJmE8tVrJCB8y4IefIMlZgd0eY8EVjq7pL9arDolDzGjePouNeOI0kiPoxmr3ecOVkNE6B0XRM56UWIBR10Ps2l9rBe9iExs4gDJ5+hChm5vJ5M8x7jDfNfJWBWvTR6rNLYuTSLlsSVb1WhsqzPImq1klWRUxCT+iP1AWWk0ZQ6pstYoRbyUBq5A63nXHUOrJ/8747I74eDGGnXVEmFpBG11ElLL0P6bP8ahf3oAdy+7JYApf78XgLvIaTIi/ue6y9yyKnwOQbsNfUwryJsNCEhDsXWIs4JpC7aONv10j+mndSaHYU4U1HyLTwvBMWei5o/0C2oX2VVGUL+xUJ7FnCSo7a3mDD01H6RfULuI2BhBvQlZnkt98qje3raBqq0lpfaL6o59zKUdk4fj7JlwLja7WndroCtmoYemmWibLM9r9dWWXvPebMPMi3LHZE6jbKNGnLYjrvEBZ7W2QYqNs9o2dnF61TvVOpfiYjJ0luNe5VjjNcN26+7keEd0ql0/4HrNodTI7zsPM1VO6MwP6GJn5dm7k6LER0G1i31554lYeSLWK6i9hcHeS8ikHVBLIZM+QR3tyJX8AN6xHje2KcNHiRsbigLZbRSIobSjOhJjdC7r7GwwOaqHEa+ffL5Ni8/Lo91nWh5sTdK/mfs8oupTm8VddH7kbVUk1EpaWgtTNarTII0vC6BeHh6KUk3xPIYd1V+2rddJvIZcVkFBaEcJCPbCs/+J5ksXj35iJxif5FU6JQ6Lc1UjmMbrJB9+SWIyP5kzmqhim3jcneOcMMi3gtxehXqjMevNOQ1hPa8kRcexe7sUdltb2DxaftnsMi0HLRyq7qGkObShlWs4p/BysL56n8J41lTHX0FWwBO14lnOvjmSUNwyZ0tBSxwtRNqLTLPtVM5TQljLkp4YElnIxirJFi2ECsZvpOBWWDORWX9PaNW1ZdW4Pwi0YSPAdJ2BCoU3mglbRAxgcdGxuBsLIJf+vSI9pms2SJv2+hhcrDYCkGOTh7XDzLHwIX6WLVzeACfIQchNVvApSfLWaeinKZ9qtq/Swsl20bZF+T6yjPalDWnPxfEP2E0CLyr8kvwa1cjC/sckw8q5eQHAhQ8Zn4R6bio3BAR78Gi+ubKKJYozVARXEAr8dJHf0lB/1mCWKc6rmGWcObxpltUCnAZXmxpr22+8x4+Y5zaXONElP4kmUhY+ItHA4Ssuk2vs6pQ8jZKtUyoGokQJ+MYXr0zdVqIDyHnlI09oJyFVLS1Ecsv9BcWtLGzGtZ54VMdMyxVmq1ya6Yajtl6LM50WU7Rt09uuzzAvTau7PqghDw3cl16jm8A9ZEXzX/5D3kGIVP0ZRug/sPDanz7Oc0E3hRe6UuakHbGcNj7+psT0HlreurQ8kgHy2VoR2oGj1RtRCcSzWQoKR7cIe0qByY0/xEgsoFDIL+DNWmZCVdyVCEsWA3YOKRYDSq/stjazkK++Sb//I1kh3cpIGl81OYdOy0hznYz+H2llVAd6fKyu+nc1Olr6b1u636JVMWL9gk1b0/3V4doFwHnY7FVX4XWNA+6PgR1RUNcBNKbwh9ep8F3ermMtPewHVdOon1pR07a2RDBAOTpUuFrVxJSbcJKauJGGpCmnrCGp5MrJaMiJVvJ7YFuabqurIsc6pY505JDeHO+DotKWjqSS52cdeeo6kjRHcx05ACU51qrcNdSRJASav9GOyuyimIkxoeozpEV+90+9EDjs3lWTkBzaT64slxq0KJVOaBJvoihmP2hQitv7wsNU66czPLoolW/835X3UdtWzwZ1KEqnZIMathBT1YpGYBxlnl01Qa5eptQCoPs7exTNlp094sSTcfZKJdI8nUZdZ2+7iw4puTql1tw9Wt+jG+EKUWv+XvOtms28u5Jy2u3u7b2rs2dvz+CntTmXHV+pfDdoGHMkMmjEm/hpcLj9z7+i+/afE50v/wA=</diagram></mxfile> diff --git a/docs/creating-a-site.txt b/docs/creating-a-site.txt index 423b2c1..0891753 100644 --- a/docs/creating-a-site.txt +++ b/docs/creating-a-site.txt @@ -1,5 +1,5 @@ .. slug: creating-a-site-not-a-blog-with-nikola -.. date: 2013/03/01 12:49:41 +.. date: 2015-01-10 10:00:00 UTC .. tags: nikola, python .. link: .. description: @@ -10,19 +10,22 @@ Creating a Site (Not a Blog) with Nikola .. class:: lead -One of the most frequent questions I get about Nikola is "but how do -I create a site that's not a blog?". And of course, that's because the -documentation is heavily blog-oriented. This document will change that ;-) +One of the most frequent questions I get about Nikola is “but how do +I create a site that’s not a blog?”. And of course, that’s because the +documentation is heavily blog–oriented. This document will change that ;-) Since it started, Nikola has had the capabilities to create generic sites. For example, -Nikola's `own site <http://getnikola.com>`_ is a fairly generic one. Let's go +Nikola’s `own site <https://getnikola.com/>`_ is a fairly generic one. Let’s go step by step on how you can do something like that. As usual when starting a nikola site, you start with ``nikola init`` which creates a -empty semi-configured site:: +empty (mostly) configured site:: $ nikola init mysite - Created empty site at mysite. + Creating Nikola Site + ==================== + ⋮ + [1970-01-01T00:00:00Z] INFO: init: Created empty site at mysite. Then we go into the new ``mysite`` folder, and make the needed changes in the ``conf.py`` configuration file: @@ -40,8 +43,8 @@ configuration file: BLOG_TITLE = "Not a Blog" # This is the main URL for your site. It will be used # in a prominent link - SITE_URL = "http://notablog.ralsina.com.ar/" - BLOG_EMAIL = "ralsina@kde.org" + SITE_URL = "https://getnikola.com/" + BLOG_EMAIL = "ralsina@example.com" BLOG_DESCRIPTION = "This is a demo site (not a blog) for Nikola." # @@ -58,12 +61,13 @@ configuration file: And now we are ready to create our first page:: - $ nikola new_post -p - Creating New Post + $ nikola new_page + Creating New Page ----------------- - Enter title: index - Your post's text is at: pages/index.txt + Title: index + Scanning posts....done! + [1970-01-01T00:00:00Z] INFO: new_page: Your page's text is at: stories/index.rst .. note:: The ``-p`` option in the ``nikola new_post`` command means we are creating a page and not a blog post. @@ -74,22 +78,20 @@ We can now build and preview our site:: . render_site:output/categories/index.html . render_sources:output/index.txt . render_rss:output/rss.xml - : - : - : [Much more of the same] - + ⋮ $ nikola serve - Serving HTTP on 127.0.0.1 port 8000 ... + [1970-01-01T00:00:00Z] INFO: serve: Serving HTTP on 0.0.0.0 port 8000... + -And you can see your (very empty) site in http://localhost:8000 +And you can see your (very empty) site in http://localhost:8000/ -So, what's in that ``pages/index.txt`` file? +So, what’s in that ``pages/index.txt`` file? .. code-block:: rest .. title: index .. slug: index - .. date: 2013/03/01 10:26:17 + .. date: 1970-01-01 00:00:00 UTC .. tags: .. link: .. description: @@ -97,43 +99,42 @@ So, what's in that ``pages/index.txt`` file? Write your post here. -Title is the page title, slug is the name of the generated HTML file -(in this case it would be ``index.html``) the date doesn't matter much in -not-blogs, same for tags and link. Description is useful for SEO purposes +``title`` is the page title, ``slug`` is the name of the generated HTML file +(in this case it would be ``index.html``). ``date``, ``tags`` and ``link`` +doesn’t matter at all in stories. ``description`` is useful for SEO purposes if you care for that. And below, the content. By default you are expected to use -`reStructuredText <http://getnikola.com/quickstart.html>`_ but +`reStructuredText <https://getnikola.com/quickstart.html>`_ but Nikola supports a ton of formats, including Markdown, plain HTML, BBCode, Wiki, and Textile. So, let's give the page a nicer title, and some fake content. Since the default -Nikola theme (called "bootstrap") is based on `bootstrap 2 <http://getbootstrap.com/2.3.2/>`_ +Nikola theme (called ``bootstrap3``) is based on `Bootstrap <http://getbootstrap.com/>`_ you can use anything you like from it: .. code-block:: rest .. title: Welcome To The Fake Site .. slug: index - .. date: 2013/03/01 10:26:17 + .. date: 1970-01-01 00:00:00 UTC .. tags: .. link: .. description: Fake Site version 1, welcome page! - .. class:: hero-unit span6 + .. class:: jumbotron col-md-6 .. admonition:: This is a Fake Site It pretends to be about things, but is really just an example. - So, don't click this button, it leads nowhere. - .. class:: btn + .. raw:: html - Click Me! + <a href="https://getnikola.com/" class="btn btn-primary btn-lg">Click Me!</a> - .. class:: span5 + .. class:: col-md-5 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris non nunc turpis. Phasellus a ullamcorper leo. Sed fringilla dapibus orci eu ornare. Quisque @@ -146,15 +147,13 @@ you can use anything you like from it: aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. - [And more in the same vein] - .. admonition:: TIP: Nice URLs - If you like your URLs without the ".html" then you want to create folders and + If you like your URLs without the ``.html`` then you want to create folders and put the pages in ``index.html`` inside them using the ``PRETTY_URLS`` option. And that's it. You will want to change the NAVIGATION_LINKS option to create a reasonable -"menu" for your site, you will want to hack the theme (check ``nikola help bootswatch_theme`` +menu for your site, you will want to modify the theme (check ``nikola help bootswatch_theme`` for a quick & dirty solution), and you may want to add a blog later on, for company news or whatever. @@ -167,9 +166,10 @@ or whatever. POSTS = [("posts/*.txt", "blog", "post.tmpl", True)] Create a post with ``nikola new_post`` and that's it, you now have a blog - in http://yoursite.com/blog (you may want to add links to it in NAVIGATION_LINKS of course). + in the ``/blog/`` subdirectory of your site — you may want to link to + it in ``NAVIGATION_LINKS``. -You can see the finished site in http://notablog.ralsina.com.ar and its full configuration in -http://ralsina.me/listings/notablog/conf.py.html +If you want to see a site implementing all of the above, check out `the Nikola +website <https://getnikola.com/>`_. I hope this was helpful! diff --git a/docs/creating-a-theme.txt b/docs/creating-a-theme.txt index 220a8e7..7113b1a 100644 --- a/docs/creating-a-theme.txt +++ b/docs/creating-a-theme.txt @@ -1,380 +1,825 @@ -.. title: Creating a Theme +.. title: Creating A Theme .. slug: creating-a-theme -.. date: 2012-03-13 12:00:00 UTC-03:00 +.. date: 2015-05-28 18:46:48 UTC .. tags: +.. category: .. link: .. description: +.. type: text -Creating A Theme From Scratch (Almost) -====================================== +Nikola is a static site and blog generator. So is Jekyll. While I like what we have done with Nikola, +I do admit that Jekyll (and others!) have many more, and nicer themes than Nikola does. -.. class:: lead +This document is an attempt at making it easier for 3rd parties (that means *you* people! ;-) to +create themes. Since I **suck** at designing websites, I asked for opinions on themes to port, +and got some feedback. Since this is **Not So Hard™**, I will try to make time to port a few +and see what happens. -There is some documentation about creating themes for Nikola, but maybe a tutorial is also a useful way -to explain it. So, here it is. I'll explain how to create a theme (almost) from scratch. All themes -in Nikola must inherit from the ``base`` theme. In this case, we will inherit from ``bootstrap`` -so we get good support for slides and galleries. +Today’s theme is `Lanyon <https://github.com/poole/lanyon>`__ which is written by `@mdo <https://twitter.com/mdo>`__ +and released under a MIT license, which is liberal enough. -I will try to create a theme that looks like `Vinicius Massuchetto's Monospace Theme <http://wordpress.org/themes/monospace>`_. +So, let’s get started. -.. TEASER_END +Checking It Out +--------------- -Starting The Theme ------------------- +The first step in porting a theme is making the original theme work. Lanyon is awesome in that its +`GitHub project <https://github.com/poole/lanyon>`__ is a full site! -First we will create a testing site:: +So:: - $ nikola init --demo monospace-site - A new site with some sample data has been created at monospace-site. - See README.txt in that folder for more information. + # Get jekyll + sudo apt-get install jekyll - $ cd monospace-site/ + # Get Lanyon + git clone git@github.com:poole/lanyon.git -Our theme will inherit from the ``bootstrap`` theme, which is full-featured but boring. + # Build it + cd lanyon && jekyll build -:: + # Look at it + jekyll serve & google-chrome http://localhost:4000 +If you **do not want to install Jekyll**, you can also see it in action at http://lanyon.getpoole.com/ + +Some things jump to my mind: + +1. This is one fine looking theme +2. Very clear and readable +3. Nice hidden navigation-thingy + +Also, from looking at `the project’s README <https://github.com/poole/lanyon/blob/master/README.md>`__ +it supports some nice configuration options: + +1. Color schemes +2. Reverse layout +3. Sidebar overlay instead of push +4. Open the sidebar by default, or on a per-page basis by using its metadata + +Let’s try to make all those nice things survive the porting. + +Starting From Somewhere +----------------------- + +Nikola has a nice, clean, base theme from which you can start when writing your own theme. +Why start from that instead of from a clean slate? Because theme inheritance is going to save you a ton of work, +that’s why. If you start from scratch you won’t be able to build **anything** until you have a bunch of +templates written. Starting from base, you just need to hack on the things you **need** to change. + +First, we create a site with some content in it. We’ll use the ``nikola init`` wizard (with the ``--demo`` option) for that:: + + $ nikola init --demo lanyon-port + Creating Nikola Site + ==================== + + This is Nikola v7.4.1. We will now ask you a few easy questions about your new site. + If you do not want to answer and want to go with the defaults instead, simply restart with the `-q` parameter. + --- Questions about the site --- + Site title [My Nikola Site]: + Site author [Nikola Tesla]: + Site author's e-mail [n.tesla@example.com]: + Site description [This is a demo site for Nikola.]: + Site URL [https://example.com/]: + --- Questions about languages and locales --- + We will now ask you to provide the list of languages you want to use. + Please list all the desired languages, comma-separated, using ISO 639-1 codes. The first language will be used as the default. + Type '?' (a question mark, sans quotes) to list available languages. + Language(s) to use [en]: + + Please choose the correct time zone for your blog. Nikola uses the tz database. + You can find your time zone here: + http://en.wikipedia.org/wiki/List_of_tz_database_time_zones + + Time zone [UTC]: + Current time in UTC: 16:02:07 + Use this time zone? [Y/n] + --- Questions about comments --- + You can configure comments now. Type '?' (a question mark, sans quotes) to list available comment systems. If you do not want any comments, just leave the field blank. + Comment system: + + That's it, Nikola is now configured. Make sure to edit conf.py to your liking. + If you are looking for themes and addons, check out https://themes.getnikola.com/ and https://plugins.getnikola.com/. + Have fun! + [2015-05-28T16:02:08Z] INFO: init: A new site with example data has been created at lanyon-port. + [2015-05-28T16:02:08Z] INFO: init: See README.txt in that folder for more information. + + +Then, we create an empty theme inheriting from base. This theme will use Mako templates. If you prefer Jinja2, +then you should use ``base-jinja`` instead:: + + $ cd lanyon-port/ $ mkdir themes - $ mkdir themes/monospace - $ echo bootstrap > themes/monospace/parent + $ mkdir themes/lanyon + $ echo base > themes/lanyon/parent -The next step is to make the testing site use this new theme, by editing ``conf.py`` and -changing the ``THEME`` option:: +Edit ``conf.py`` and set ``THEME = 'lanyon'``. Also set ``USE_BUNDLES = False`` (just do it for now, we’ll get to bundles later). - # Name of the theme to use. Themes are located in themes/theme_name - THEME = 'monospace' +You can now build that site using ``nikola build`` and it will look like this: -Now we can already build and test the site:: +.. figure:: https://getnikola.com/images/lanyon-0.thumbnail.png + :target: https://getnikola.com/images/lanyon-0.png - $ nikola build && nikola serve + This is just the base theme. -.. figure:: http://ralsina.com.ar/galleries/monospace-tut/monospace-1.png - :height: 400px +Basic CSS +--------- - This is the default "bootstrap" theme. +The next step is to know exactly how Lanyon’s pages work. To do this, we read its HTML. +First let’s look at the head element: -Of course, the page layout is completely different from what we want. To fix that, we need to -get into templates. +.. code:: html -Templates: Page Layout ----------------------- + <!DOCTYPE html> + <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en-us"> -The general page layout for the theme is done by the ``base.tmpl`` template, which is done using -`Mako <http://www.makotemplates.org/>`_. This is bootstrap's ``base.tmpl``, it's not very big: + <head> + <link href="http://gmpg.org/xfn/11" rel="profile"> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> -.. code-block:: mako + <!-- Enable responsiveness on mobile devices--> + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1"> + + <title> + Lanyon · A Jekyll theme + </title> + + <!-- CSS --> + <link rel="stylesheet" href="/public/css/poole.css"> + <link rel="stylesheet" href="/public/css/syntax.css"> + <link rel="stylesheet" href="/public/css/lanyon.css"> + <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=PT+Serif:400,400italic,700|PT+Sans:400"> + + <!-- Icons --> + <link rel="apple-touch-icon-precomposed" sizes="144x144" href="/public/apple-touch-icon-144-precomposed.thumbnail.png"> + <link rel="shortcut icon" href="/public/favicon.ico"> + + <!-- RSS --> + <link rel="alternate" type="application/rss+xml" title="RSS" href="/atom.xml"> + + <!-- Google Analytics --> + [...] + </head> + +The interesting part there is that it loads a few CSS files. If you check the source of your Nikola site, you will +see something fairly similar: + +.. code:: html - ## -*- coding: utf-8 -*- - <%namespace name="base" file="base_helper.tmpl" import="*" /> - <%namespace name="bootstrap" file="bootstrap_helper.tmpl" import="*" /> - ${set_locale(lang)} <!DOCTYPE html> - <html% if comment_system == 'facebook': xmlns:fb="http://ogp.me/ns/fb#" %endif lang="${lang}"> + <html prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article# " vocab="http://ogp.me/ns" lang="en"> <head> - <meta name="viewport" content="width=device-width, initial-scale=1.0"> - ${bootstrap.html_head()} - <%block name="extra_head"> - </%block> - ${extra_head_data} + <meta charset="utf-8"> + <meta name="description" content="This is a demo site for Nikola."> + <meta name="viewport" content="width=device-width"> + <title>My Nikola Site | My Nikola Site</title> + + <link href="assets/css/rst.css" rel="stylesheet" type="text/css"> + <link href="assets/css/code.css" rel="stylesheet" type="text/css"> + <link href="assets/css/theme.css" rel="stylesheet" type="text/css"> + + <link rel="alternate" type="application/rss+xml" title="RSS" href="rss.xml"> + <link rel="canonical" href="https://example.com/index.html"> + <!--[if lt IE 9]><script src="assets/js/html5.js"></script><![endif]--><link rel="prefetch" href="posts/welcome-to-nikola.html" type="text/html"> </head> - <body> - <!-- Menubar --> - <div class="navbar navbar-fixed-top" id="navbar"> - <div class="navbar-inner"> - <div class="container"> - <!-- .btn-navbar is used as the toggle for collapsed navbar content --> - <a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse"> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - <span class="icon-bar"></span> - </a> - - <a class="brand" href="${abs_link('/')}"> - ${blog_title} - </a> - <!-- Everything you want hidden at 940px or less, place within here --> - <div class="nav-collapse collapse"> - <ul class="nav"> - ${bootstrap.html_navigation_links()} - </ul> - %if search_form: - ${search_form} - %endif - <ul class="nav pull-right"> - <%block name="belowtitle"> - %if len(translations) > 1: - <li>${base.html_translations()}</li> - %endif - </%block> - % if show_sourcelink: - <li><%block name="sourcelink"></%block></li> - %endif - </ul> - </div> - </div> - </div> - </div> - <!-- End of Menubar --> - <div class="container-fluid" id="container-fluid"> - <!--Body content--> - <div class="row-fluid"> - <div class="span2"></div> - <div class="span8"> - <%block name="content"></%block> - </div> + + +Luckily, since this is all under a very liberal license, we can just copy these CSS files into +Nikola, adapting the paths a little so that they follow our conventions:: + + $ mkdir -p themes/lanyon/assets/css + $ cp ../lanyon/public/css/poole.css themes/lanyon/assets/css/ + $ cp ../lanyon/public/css/lanyon.css themes/lanyon/assets/css/ + +Notice I am *not* copying ``syntax.css``? That’s because Nikola handles that styles for syntax highlighting +in a particular way, using a setting called ``CODE_COLOR_SCHEME`` where you can configure +what color scheme the syntax highlighter uses. You can use your own ``assets/css/code.css`` if you +don’t like the provided ones. + +Nikola **requires** ``assets/css/rst.css`` and ``assets/css/code.css`` to function properly. +We will also add themes for IPython Notebook (``assets/css/ipython.min.css`` +and ``assets/css/nikola_ipython.css``) into the template; note that they are +activated only if you configured your ``POSTS``/``PAGES`` with ipynb support. + +But how do I tell **our** lanyon theme to use those CSS files instead of whatever it’s using now? +By giving our theme its own base_helper.tmpl. + +That file is a **template** used to generate parts of the pages. It’s large and +complicated but we don’t need to change a lot of it. First, get it from +`Nikola’s source code <https://github.com/getnikola/nikola/blob/master/nikola/data/themes/base/templates/base_helper.tmpl>`__ and put a copy in ``themes/lanyon/templates/base_helper.tmpl``:: + + $ mkdir themes/lanyon/templates + $ curl https://raw.githubusercontent.com/getnikola/nikola/master/nikola/data/themes/base/templates/base_helper.tmpl > themes/lanyon/templates/base_helper.tmpl + +The part we want to change is this: + +.. code:: html+mako + + <%def name="html_stylesheets()"> + %if use_bundles: + %if use_cdn: + <link href="/assets/css/all.css" rel="stylesheet" type="text/css"> + %else: + <link href="/assets/css/all-nocdn.css" rel="stylesheet" type="text/css"> + %endif + %else: + <link href="/assets/css/rst.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/code.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/theme.css" rel="stylesheet" type="text/css"> + %if has_custom_css: + <link href="/assets/css/custom.css" rel="stylesheet" type="text/css"> + %endif + %endif + % if needs_ipython_css: + <link href="/assets/css/ipython.min.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/nikola_ipython.css" rel="stylesheet" type="text/css"> + % endif + </%def> + +And we will change it so it uses the lanyon styles instead of theme.css (again, ignore the bundles for now!): + +.. code:: html+mako + + <%def name="html_stylesheets()"> + %if use_bundles: + <link href="/assets/css/all.css" rel="stylesheet" type="text/css"> + %else: + <link href="/assets/css/rst.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/poole.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/lanyon.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/code.css" rel="stylesheet" type="text/css"> + %if has_custom_css: + <link href="/assets/css/custom.css" rel="stylesheet" type="text/css"> + %endif + %endif + % if needs_ipython_css: + <link href="/assets/css/ipython.min.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/nikola_ipython.css" rel="stylesheet" type="text/css"> + % endif + <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=PT+Serif:400,400italic,700|PT+Sans:400"> + </%def> + +.. figure:: https://getnikola.com/images/lanyon-1.thumbnail.png + :target: https://getnikola.com/images/lanyon-1.png + + You may say this looks like crap. Don’t worry, we are just starting :-) + +Page Layout +----------- + +This is trickier but should be no problem for people with a basic understanding of HTML and a desire to make a theme! + +Lanyon’s content is split in two parts: a sidebar and the rest. The sidebar looks like this (shortened for comprehension): + +.. code:: html + + <body> + <!-- Target for toggling the sidebar `.sidebar-checkbox` is for regular + styles, `#sidebar-checkbox` for behavior. --> + <input type="checkbox" class="sidebar-checkbox" id="sidebar-checkbox"> + + <!-- Toggleable sidebar --> + <div class="sidebar" id="sidebar"> + <div class="sidebar-item"> + <p>A reserved <a href="http://jekyllrb.com" target="_blank">Jekyll</a> theme that places the utmost gravity on content with a hidden drawer. Made by <a href="https://twitter.com/mdo" target="_blank">@mdo</a>.</p> </div> - <!--End of body content--> - </div> - <div class="footerbox"> - ${content_footer} + + <nav class="sidebar-nav"> + <a class="sidebar-nav-item active" href="/">Home</a> + <a class="sidebar-nav-item" href="/about/">About</a> + [...] + </nav> </div> - ${bootstrap.late_load_js()} - ${base.html_social()} - <script>jQuery("a.image-reference").colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true}); - $(window).on('hashchange', function(){ - if (location.hash && $(location.hash)[0]) { - $('body').animate({scrollTop: $(location.hash).offset().top - $('#navbar').outerHeight(true)*1.2 }, 1); - } - }); - $(document).ready(function(){$(window).trigger('hashchange')}); - </script> - <%block name="extra_js"></%block> - ${body_end} - </body> +So, a plain body, with an input element that controls the sidebar, a div which is the sidebar itself. +Inside that, div.sidebar-item for items, and a nav with "navigational links". This is followed by the "masthead" and +the content itself, which we will look at in a bit. + +If we look for the equivalent code in Nikola’s side, we see this: + +.. code:: html + + <body> + <a href="#content" class="sr-only sr-only-focusable">Skip to main content</a> + <div id="container"> + <header id="header" role="banner"> + <h1 id="brand"><a href="https://example.com/" title="My Nikola Site" rel="home"> <span id="blog-title">My Nikola Site</span> </a></h1> + <nav id="menu" role="navigation"><ul> + <li><a href="../archive.html">Archive</a></li> + <li><a href="../categories/index.html">Tags</a></li> + <li><a href="../rss.xml">RSS feed</a></li> + +So Nikola has the "masthead" above the nav element, and uses list elements in nav instead of bare links. +Not all that different is it? -It's basically a HTML document with some placeholders to be replaced with actual content, configuration options, and some helper functions. -For example, the ``html_head`` helper can be used to add CSS or JS files in all document's ``head`` tags. +Let’s make it lanyon-like! We will need 2 more templates: `base.tmpl <https://github.com/getnikola/nikola/blob/master/nikola/data/themes/base/templates/base.tmpl>`__ and `base_header.tmpl <https://github.com/getnikola/nikola/blob/master/nikola/data/themes/base/templates/base_header.tmpl>`__. Get them and put them in your ``themes/lanyon/templates`` folder. -Monospace is a two-column-with-footer layout, so let's copy the basics from its HTML and see what happens: +Let’s look at ``base.tmpl`` first. It’s short and nice, it looks like a webpage without +all the interesting stuff: -.. code-block:: mako +.. code:: html+mako ## -*- coding: utf-8 -*- <%namespace name="base" file="base_helper.tmpl" import="*"/> - <%namespace name="bootstrap" file="bootstrap_helper.tmpl" import="*" /> + <%namespace name="header" file="base_header.tmpl" import="*"/> + <%namespace name="footer" file="base_footer.tmpl" import="*"/> + <%namespace name="annotations" file="annotation_helper.tmpl"/> ${set_locale(lang)} - <!DOCTYPE html> - <html lang="${lang}"> - <head> - ${bootstrap.html_head()} - <%block name="extra_head"> - </%block> - ${extra_head_data} + ${base.html_headstart()} + <%block name="extra_head"> + ### Leave this block alone. + </%block> + ${template_hooks['extra_head']()} </head> - <body class="home blog"> - <div id="wrap" style="width:850px"> - <div id="container" style="width:560px"> + <body> + <a href="#content" class="sr-only sr-only-focusable">${messages("Skip to main content")}</a> + <div id="container"> + ${header.html_header()} + <main id="content" role="main"> <%block name="content"></%block> + </main> + ${footer.html_footer()} + </div> + ${body_end} + ${template_hooks['body_end']()} + ${base.late_load_js()} + </body> + </html> + +That link which says "Skip to main content" is very important for accessibility, so we will leave it in +place. But below, you can see how it creates the "container" div we see in the Nikola page, and the content is +created by ``html_header()`` which is defined in ``base_header.tmpl`` The actual ``nav`` element is done +by the ``html_navigation_links`` function out of the ``NAVIGATION_LINKS`` option. + +So, first, lets change that base template to be more lanyon-like: + +.. code:: html+mako + + ## -*- coding: utf-8 -*- + <%namespace name="base" file="base_helper.tmpl" import="*"/> + <%namespace name="header" file="base_header.tmpl" import="*"/> + <%namespace name="footer" file="base_footer.tmpl" import="*"/> + <%namespace name="annotations" file="annotation_helper.tmpl"/> + ${set_locale(lang)} + ${base.html_headstart()} + <%block name="extra_head"> + ### Leave this block alone. + </%block> + ${template_hooks['extra_head']()} + </head> + <body> + <a href="#content" class="sr-only sr-only-focusable">${messages("Skip to main content")}</a> + <!-- Target for toggling the sidebar `.sidebar-checkbox` is for regular + styles, `#sidebar-checkbox` for behavior. --> + <input type="checkbox" class="sidebar-checkbox" id="sidebar-checkbox"> + + <!-- Toggleable sidebar --> + <div class="sidebar" id="sidebar"> + <div class="sidebar-item"> + <p>A reserved <a href="http://getnikola.com" target="_blank">Nikola</a> theme that places the utmost gravity on content with a hidden drawer. Made by <a href="https://twitter.com/mdo" target="_blank">@mdo</a> for Jekyll, + ported to Nikola by <a href="https://twitter.com/ralsina" target="_blank">@ralsina</a>.</p> </div> - <div id="sidebar"> - <!--Sidebar content--> - <h1 id="blog-title"> - <a href="${abs_link('/')}" title="${blog_title}">${blog_title}</a> - </h1> - <%block name="belowtitle"> - %if len(translations) > 1: - <small> - ${(messages("Also available in"))}: - ${base.html_translations()} - </small> - %endif - </%block> - <ul class="unstyled"> - <li>${license} - ${base.html_social()} - ${bootstrap.html_navigation_links()} - <li>${search_form} - </ul> - </div> - <div id="footer"> - ${content_footer} + ${header.html_navigation_links()} + </div> + + <main id="content" role="main"> + <%block name="content"></%block> + </main> + ${footer.html_footer()} + ${body_end} + ${template_hooks['body_end']()} + ${base.late_load_js()} + </body> + </html> + +.. figure:: https://getnikola.com/images/lanyon-2.thumbnail.png + :target: https://getnikola.com/images/lanyon-2.png + + And that’s after I exposed the sidebar by clicking on an invisible widget! + +One problem, which causes that yellow color in the sidebar is a CSS conflict. +We are loading ``rst.css`` which specifies +the background color of ``div.sidebar`` which is more specific than +``lanyon.css``, which specifies for ``.sidebar`` alone. + +There are many ways to fix this, I chose to change lanyon.css to also use div.sidebar: + +.. code:: css + + div.sidebar,.sidebar { + position: fixed; + top: 0; + bottom: 0; + left: -14rem; + width: 14rem; + [...] + +This is annoying but it will happen when you just grab CSS from different places. The "Inspect Element" +feature of your web browser is your best friend for these situations. + +Another problem is that the contents of the nav element are wrong. They are not bare links. We will fix that in +``base_header.html``, like this: + +.. code:: html+mako + + <%def name="html_navigation_links()"> + <nav id="menu" role="navigation" class="sidebar-nav"> + %for url, text in navigation_links[lang]: + <a class="sidebar-nav-item" href="${url}">${text}</a> + %endfor + ${template_hooks['menu']()} + ${template_hooks['menu_alt']()} + </nav> + </%def> + +**Note: this means this theme will not support submenus in navigation. If you want that, I’ll happily take a patch.** + +.. figure:: https://getnikola.com/images/lanyon-3.thumbnail.png + :target: https://getnikola.com/images/lanyon-3.png + + Starting to see a resemblance? + +Now let’s look at the content. In Lanyon, this is how the "main" content looks: + +.. code:: html + + <!-- Wrap is the content to shift when toggling the sidebar. We wrap the + content to avoid any CSS collisions with our real content. --> + <div class="wrap"> + <div class="masthead"> + <div class="container"> + <h3 class="masthead-title"> + <a href="/" title="Home">Lanyon</a> + <small>A Jekyll theme</small> + </h3> + </div> + </div> + + <div class="container content"> + <div class="post"> + <h1 class="post-title">Introducing Lanyon</h1> + <span class="post-date">02 Jan 2014</span> + <p>Lanyon is an unassuming <a href="http://jekyllrb.com">Jekyll</a> theme [...] + </div> + </div> + </div> + <label for="sidebar-checkbox" class="sidebar-toggle"></label> + </body> + </html> + +Everything inside the "container content" div is… the content. The rest is a masthead with the site title +and at the bottom a label for the sidebar toggle. Easy to do in ``base.tmpl`` +(only showing the relevant part): + +.. code:: html+mako + + <!-- Wrap is the content to shift when toggling the sidebar. We wrap the + content to avoid any CSS collisions with our real content. --> + <div class="wrap"> + <div class="masthead"> + <div class="container"> + <h3 class="masthead-title"> + <a href="/" title="Home">Lanyon</a> + <small>A Jekyll theme</small> + </h3> </div> </div> - ${bootstrap.late_load_js()} - <script>jQuery("a.image-reference").colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});</script> - <%block name="extra_js"></%block> + + <div class="container content" id="content"> + <%block name="content"></%block> + </div> + </div> + <label for="sidebar-checkbox" class="sidebar-toggle"></label> + ${footer.html_footer()} ${body_end} + ${template_hooks['body_end']()} + ${base.late_load_js()} </body> + </html> + +.. figure:: https://getnikola.com/images/lanyon-4.thumbnail.png + :target: https://getnikola.com/images/lanyon-4.png + + Getting there! + +The sidebar looks bad because of yet more CSS conflicts with ``rst.css``. By +adding some extra styling in ``lanyon.css``, it will look better. + +.. code:: css + + /* Style and "hide" the sidebar */ + div.sidebar, .sidebar { + position: fixed; + top: 0; + bottom: 0; + left: -14rem; + width: 14rem; + visibility: hidden; + overflow-y: auto; + padding: 0; + margin: 0; + border: none; + font-family: "PT Sans", Helvetica, Arial, sans-serif; + font-size: .875rem; /* 15px */ + color: rgba(255,255,255,.6); + background-color: #202020; + -webkit-transition: all .3s ease-in-out; + transition: all .3s ease-in-out; + } + +Also, the accessibility link on top is visible when it should not. That’s +because we removed ``theme.css`` from the base theme, and with it, we lost a +couple of classes. We can add them in ``lanyon.css``, along with others used by other +pieces of the site: + +.. code:: css + + .sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + } + + .sr-only-focusable:active, + .sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; + } + + .breadcrumb { + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + } -.. figure:: http://ralsina.com.ar/galleries/monospace-tut/monospace-2.png - - Yikes! - -This will get better quickly once we add some CSS - - -Base CSS --------- - -The orphan theme includes just a little styling, specifically ``rest.css`` so -the reStructuredText output looks reasonable, and ``code.css`` for code snippets. - -It also includes an empty ``assets/css/theme.css`` where you can add your own CSS. -For example, this is taken from the original monospace theme, except for the last -few selectors: - -.. code-block:: css - - body { margin:0px; padding:20px 0px; text-align:center; font-family:Monospace; color:#585858; } - .post { margin:0px 0px 30px 0px; padding:0px 0px 30px 0px; border-bottom:1px dotted #C8C8C8; } - .meta { margin:10px; padding:15px; background:#EAEAEA; clear:both; } - #footer { text-align:center; clear:both; margin:30px 0px 0px 0px; padding:30px 0px 0px 0px; border-top:1px dotted #C8C8C8; } - #wrap { margin:0px auto; text-align:left; font-size: 13px; line-height: 1.4; } - #container { float:right; } - #sidebar { overflow:hidden; clear:left; text-align:right; width:250px; height:auto; padding:0px 15px 0px 0px; border-right:1px dotted #C8C8C8; } - #sidebar li { list-style-type:none; } - #sidebar > li { margin:20px 0px; } - #sidebar h1 { border-bottom:1px dotted #C8C8C8; } - #sidebar .description { display:block; width:100%; height:auto; margin:0px 0px 10px 0px; } - h1, h2, h3, h4, h5, h6, h7 { margin:0px; text-transform:uppercase; } - h4, h5, h6 { font-size:14px; } - #blog-title { margin-top: 0; line-height:48px;} - .literal-block {padding: .5em;} - div.sidebar, div.admonition, div.attention, div.caution, div.danger, div.error, div.hint, div.important, div.note, div.tip, div.warning { - /* Issue 277 */ - border: 1px solid #aaa; - border-radius: 5px; - width: 100%; + .breadcrumb > li { + display: inline-block; + margin-right: 0; + margin-left: 0; } - ul.breadcrumb > li:before { - content: " / "; + + .breadcrumb > li:after { + content: ' / '; + color: #888; + } + + .breadcrumb > li:last-of-type:after { + content: ''; + margin-left: 0; + } + + .thumbnails > li { + display: inline-block; + margin-right: 10px; + } + + .thumbnails > li:last-of-type { + margin-right: 0; } -This will (after we rebuild it) make the site looks different of course, and getting closer to our goal: -.. figure:: http://ralsina.com.ar/galleries/monospace-tut/monospace-3.png - :height: 400px +.. figure:: https://getnikola.com/images/lanyon-5.thumbnail.png + :target: https://getnikola.com/images/lanyon-5.png + + Little by little, things look better. + +One clear problem is that the title "Lanyon · A Jekyll theme" is set in the +theme itself. We don’t do that sort of thing in Nikola, we have settings for +that. So, let’s use them. There is a ``html_site_title`` function in +``base_helper.tmpl`` which is just the thing. So we change base.tmpl to use it: + +.. code:: html+mako + + <div class="wrap"> + <div class="masthead"> + <div class="container"> + ${header.html_site_title()} + </div> + </div> + +That’s a ``<h1>`` instead of a ``<h3>`` like Lanyon does, but hey, it’s the +right thing to do. If you want to go with an ``<h3>``, just +change ``html_site_title`` itself. + +And now we more or less have the correct page layout and styles. Except for a +rather large thing… + +Typography +---------- + +You can see in the previous screenshot that text still looks quite different in our port: Serif versus Sans-Serif +content, and the titles have different colors! + +Let’s start with the titles. Here’s how they look in Lanyon: + +.. code:: html + + <h3 class="masthead-title"> + <a href="/" title="Home">Lanyon</a> + <small>A Jekyll theme</small> + </h3> + +Versus our port: + +.. code:: html + + <h1 id="brand"><a href="https://example.com/" title="My Nikola Site" rel="home"> + +So, it looks like we will have to fix ``html_site_title`` after all: - Monospaced allright. +.. code:: html+mako -If you compare it to `the original <http://wp-themes.com/monospace/>`_, however, you will see that the layout of -the posts themselves is different, and that was not described in ``base.tmpl`` at all. But if you look, you'll see that -there is a placeholder called content: ``<%block name="content"></%block>`` + <%def name="html_site_title()"> + <h3 id="brand" class="masthead-title"> + <a href="${abs_link(_link("root", None, lang))}" title="${blog_title}" rel="home">${blog_title}</a> + </h3> + </%def> -That's because ``base.tmpl`` defines the *base* layout. The layout of more specific pages, like "the page that shows -a list of posts" is defined in the other templates. Specifically, this is defined in ``index.tmpl``. -It turns out ``bootstrap`` doesn' have one of those! That's because it inherits that template from ``base``: +As for the actual content, that’s not in any of the templates we have seen so far. The page you see is an +"index.tmpl" page, which means it’s a list of blog posts shown one below the +other. Obviously it’s not doing +things in the way the Lanyon CSS expects it to. Here’s the original, which you +can find in Nikola’s source +code: -.. code-block:: mako +.. code:: html+mako ## -*- coding: utf-8 -*- <%namespace name="helper" file="index_helper.tmpl"/> <%namespace name="comments" file="comments_helper.tmpl"/> <%inherit file="base.tmpl"/> + + <%block name="extra_head"> + ${parent.extra_head()} + % if posts and (permalink == '/' or permalink == '/' + index_file): + <link rel="prefetch" href="${posts[0].permalink()}" type="text/html"> + % endif + </%block> + <%block name="content"> - % for post in posts: - <div class="postbox post-${post.meta('type')}"> - <h1><a href="${post.permalink()}">${post.title()}</a> - <small> - ${messages("Posted")}: <time class="published" datetime="${post.date.isoformat()}">${post.formatted_date(date_format)}</time> - </small></h1> - <hr> - ${post.text(teaser_only=index_teasers)} - % if not post.meta('nocomments'): - ${comments.comment_link(post.permalink(), post.base_path)} - % endif + <%block name="content_header"></%block> + <div class="postindex"> + % for post in posts: + <article class="h-entry post-${post.meta('type')}"> + <header> + <h1 class="p-name entry-title"><a href="${post.permalink()}" class="u-url">${post.title()|h}</a></h1> + <div class="metadata"> + <p class="byline author vcard"><span class="byline-name fn">${post.author()}</span></p> + <p class="dateline"><a href="${post.permalink()}" rel="bookmark"><time class="published dt-published" datetime="${post.date.isoformat()}" title="${post.formatted_date(date_format)}">${post.formatted_date(date_format)}</time></a></p> + % if not post.meta('nocomments') and site_has_comments: + <p class="commentline">${comments.comment_link(post.permalink(), post._base_path)} + % endif </div> - % endfor - ${helper.html_pager()} - ${comments.comment_link_script()} - ${helper.mathjax_script(posts)} + </header> + %if index_teasers: + <div class="p-summary entry-summary"> + ${post.text(teaser_only=True)} + %else: + <div class="e-content entry-content"> + ${post.text(teaser_only=False)} + %endif + </div> + </article> + % endfor + </div> + ${helper.html_pager()} + ${comments.comment_link_script()} + ${helper.mathjax_script(posts)} </%block> -So, let's tweak that to be closer to the original. We put the post's metadata in a -box, add links for the posts tags, move the date there, etc. -.. code-block:: mako +And this is how it looks after I played with it for a while, making it generate code that looks closer to +the Lanyon original: + +.. code:: html+mako - ## -*- coding: utf-8 -*- - <%namespace name="helper" file="index_helper.tmpl"/> - <%namespace name="disqus" file="disqus_helper.tmpl"/> - <%inherit file="base.tmpl"/> <%block name="content"> - % for post in posts: - <div class="postbox post-${post.meta('type')}"> - <h1><a href="${post.permalink()}">${post.title()}</a></h1> - <div class="meta" style="background-color: rgb(234, 234, 234); "> - <span class="authordate"> - ${messages("Posted")}: ${post.formatted_date(date_format)} - </span> - <br> - <span class="tags">Tags: - %if post.tags: - %for tag in post.tags: - <a class="tag" href="${_link('tag', tag)}"><span>${tag}</span></a> - %endfor - %endif - </span> - </div> - ${post.text(teaser_only=index_teasers)} - % if not post.meta('nocomments'): - ${disqus.html_disqus_link(post.permalink()+"#disqus_thread", post.base_path)} - % endif + <%block name="content_header"></%block> + <div class="posts"> + % for post in posts: + <article class="post h-entry post-${post.meta('type')}"> + <header> + <h1 class="post-title p-name"><a href="${post.permalink()}" class="u-url">${post.title()|h}</a></h1> + <div class="metadata"> + <p class="byline author vcard"><span class="byline-name fn">${post.author()}</span></p> + <p class="dateline"><a href="${post.permalink()}" rel="bookmark"><time class="post-date published dt-published" datetime="${post.date.isoformat()}" title="${post.formatted_date(date_format)}">${post.formatted_date(date_format)}</time></a></p> + % if not post.meta('nocomments') and site_has_comments: + <p class="commentline">${comments.comment_link(post.permalink(), post._base_path)} + % endif </div> - % endfor - ${helper.html_pager()} - ${disqus.html_disqus_script()} + </header> + %if index_teasers: + <div class="p-summary entry-summary"> + ${post.text(teaser_only=True)} + %else: + <div class="e-content entry-content"> + ${post.text(teaser_only=False)} + %endif + </div> + </article> + % endfor + </div> + ${helper.html_pager()} + ${comments.comment_link_script()} + ${helper.mathjax_script(posts)} </%block> +With these changes, it looks… similar? -.. figure:: http://ralsina.com.ar/galleries/monospace-tut/monospace-4.png - :height: 400px +.. figure:: https://getnikola.com/images/lanyon-6.thumbnail.png + :target: https://getnikola.com/images/lanyon-6.png - Close enough! + It does! -Then if we click on the post title, we will see some broken details in the metadata that can be fixed in ``post.tmpl``, and so on. +Similar changes (basically adding class names to elements) needed to be done in ``post_header.tmpl``: -.. code-block:: mako +.. code:: html+mako - ## -*- coding: utf-8 -*- - <%namespace name="helper" file="post_helper.tmpl"/> - <%namespace name="disqus" file="disqus_helper.tmpl"/> - <%inherit file="base.tmpl"/> - <%block name="extra_head"> - ${helper.twitter_card_information(post)} - % if post.meta('keywords'): - <meta name="keywords" content="${post.meta('keywords')|h}"/> - % endif - </%block> - <%block name="content"> - <div class="post"> - ${helper.html_title()} - <div class="meta" style="background-color: rgb(234, 234, 234); "> - <span class="authordate"> - ${messages("Posted")}: ${post.formatted_date(date_format)} - % if not post.meta('password'): - [<a href="${post.source_link()}" id="sourcelink">${messages("Source")}</a>] + <%def name="html_post_header()"> + <header> + ${html_title()} + <div class="metadata"> + <p class="byline author vcard"><span class="byline-name fn">${post.author()}</span></p> + <p class="dateline"><a href="${post.permalink()}" rel="bookmark"><time class="post-date published dt-published" datetime="${post.date.isoformat()}" itemprop="datePublished" title="${post.formatted_date(date_format)}">${post.formatted_date(date_format)}</time></a></p> + % if not post.meta('nocomments') and site_has_comments: + <p class="commentline">${comments.comment_link(post.permalink(), post._base_path)} % endif - </span> - <br> - %if post.tags: - <span class="tags">${messages("Tags")}: - %for tag in post.tags: - <a class="tag" href="${_link('tag', tag)}"><span>${tag}</span></a> - %endfor - </span> - <br> + %if post.description(): + <meta name="description" itemprop="description" content="${post.description()}"> %endif - <span class="authordate"> - ${helper.html_translations(post)} - </span> </div> - ${post.text()} - ${helper.html_pager(post)} - % if not post.meta('nocomments'): - ${disqus.html_disqus(post.permalink(absolute=True), post.title(), post.base_path)} - % endif - </div> - </%block> + ${html_translations(post)} + </header> + </%def> + +Customization +------------- + +The original Lanyon theme supports some personalization options. It suggests you do them by tweaking the templates, and +you *can* also do that in the Nikola port. But we prefer to use options for that, so that you can get a later, better +version of the theme and it will still "just work". + +Let’s see the color schemes first. They apply easily, just tweak your ``body`` element like this: + +.. code:: html + + <body class="theme-base-08"> + ... + </body> + +We can tweak ``base.tmpl`` to do just that: + +.. code:: html+mako + + % if lanyon_subtheme: + <body class="${lanyon_subtheme}"> + %else: + <body> + %endif + +And then we can put the options in conf.py’s ``GLOBAL_CONTEXT``: + +.. code:: python + + GLOBAL_CONTEXT = { + "lanyon_subtheme": "theme-base-08" + } + +.. figure:: https://getnikola.com/images/lanyon-7.thumbnail.png + :target: https://getnikola.com/images/lanyon-7.png + + Look at it, all themed up. + +Doing the same for layout-reverse, sidebar-overlay and the rest is left as an exercise for the reader. + +Bundles +------- + +If you have ``webassets`` installed and the ``USE_BUNDLES`` option set to True, Nikola can put several CSS or JS files together in a larger file, +which makes sites load faster. To do that, your theme needs a ``bundles`` file where the syntax is:: + + outputfile1.js=thing1.js,thing2.js,... + outputfile2.css=thing1.css,thing2.css,... + +For the Lanyon theme, it should be like this:: + assets/css/all.css=rst.css,code.css,poole.css,lanyon.css,custom.css -.. figure:: http://ralsina.com.ar/galleries/monospace-tut/monospace-5.png - :height: 400px +**Note:** Some themes also support the ``USE_CDN`` option meaning that in some cases it will load one bundle with all CSS and in other will load some CSS files +from a CDN and others from a bundle. This is complicated and probably not worth the effort. - Details, details. +The End +------- -The demo site exercises most of the features in Nikola, so if you make it look good, your site probably will look good too. -This monospace theme is included with nikola, if you want to use it or play with it. +And that’s it, that’s a whole theme. Eventually, once people start using it, they will notice small broken details, which will need handling one at a time. +This theme should be available in http://themes.getnikola.com#lanyon and you can see it in action at https://themes.getnikola.com/v7/lanyon/index.html diff --git a/docs/extending.txt b/docs/extending.txt index bb337f7..9db5344 100644 --- a/docs/extending.txt +++ b/docs/extending.txt @@ -8,7 +8,7 @@ Extending Nikola ================ -:Version: 7.1.0 +:Version: 7.6.0 :Author: Roberto Alsina <ralsina@netmanagers.com.ar> .. class:: alert alert-info pull-right @@ -38,7 +38,7 @@ When you run ``nikola --help`` you will see something like this:: $ nikola help Nikola is a tool to create static websites and blogs. For full documentation and more - information, please visit http://getnikola.com + information, please visit https://getnikola.com/ Available commands: @@ -87,7 +87,7 @@ First, the ``serve.plugin`` file: [Documentation] Author = Roberto Alsina Version = 0.1 - Website = http://getnikola.com + Website = https://getnikola.com Description = Start test server. .. note:: If you want to publish your plugin on the Plugin Index, `read @@ -179,7 +179,7 @@ First, you have to create a .plugin file. Here's the one for the Mako plugin: [Documentation] Author = Roberto Alsina Version = 0.1 - Website = http://getnikola.com + Website = https://getnikola.com Description = Support for Mako templates. .. note:: If you want to publish your plugin on the Plugin Index, `read @@ -205,31 +205,41 @@ a stub for a hypothetical system called "Templater": # name has to match Name in the .plugin file name = "templater" + # A list of directories where the templates will be + # located. Most template systems have some sort of + # template loading tool that can use this. + def set_directories(self, directories, cache_folder): + """Sets the list of folders where templates are located and cache.""" + pass + # You *must* implement this, even if to return [] # It should return a list of all the files that, # when changed, may affect the template's output. # usually this involves template inheritance and # inclusion. - def get_deps(self, filename): + def template_deps(self, template_name): + """Returns filenames which are dependencies for a template.""" return [] - # A list of directories where the templates will be - # located. Most template systems have some sort of - # template loading tool that can use this. + def render_template(self, template_name, output_name, context): + """Renders template to a file using context. - def set_directories(self, directories): - """Create a template lookup.""" + This must save the data to output_name *and* return it + so that the caller may do additional processing. + """ pass # The method that does the actual rendering. # template_name is the name of the template file, - # output_name is the file for the output, context - # is a dictionary containing the data the template + # context is a dictionary containing the data the template # uses for rendering. + def render_template_to_string(self, template, context): + """Renders template to a string using context. """ + pass - def render_template(self, template_name, output_name, - context, global_context): - """Render the template into output_name using context.""" + def inject_directory(self, directory): + """Injects the directory with the lowest priority in the + template search mechanism.""" pass @@ -240,7 +250,7 @@ If you want to do something that depends on the data in your site, you probably want to do a Task plugin, which will make it be part of the ``nikola build`` command. There are the currently available tasks, all provided by plugins: - +T .. sidebar:: Other Tasks There are also ``LateTask`` plugins, which are executed later, @@ -290,7 +300,7 @@ in the logical ways: [Documentation] Author = Roberto Alsina Version = 0.1 - Website = http://getnikola.com + Website = https://getnikola.com Description = Copy theme assets into output. @@ -364,6 +374,10 @@ They must provide: If the compiler produces something other than HTML files, it should also implement ``extension`` which returns the preferred extension for the output file. +These plugins can also be used to extract metadata from file. To do so, the +plugin may implement ``read_metadata`` that will return a dict containing the +metadata contained in the file. + RestExtension Plugins --------------------- @@ -393,9 +407,11 @@ Currently Nikola emits the following signals: When all the configuration file is processed. Note that plugins are activated before this is emitted. ``scanned`` After posts are scanned. -``new_post`` - When a new post is created, using the ``nikola new_post`` command. The signal +``new_post`` / ``new_page`` + When a new post is created, using the ``nikola new_post``/``nikola new_page`` commands. The signal data contains the path of the file, and the metadata file (if there is one). +``existing_post`` / ``existing_page`` + When a new post fails to be created due to a title conflict. Contains the same data as ``new_post``. ``deployed`` When the ``nikola deploy`` command is run, and there is at least one new entry/post since ``last_deploy``. The signal data is of the form:: @@ -408,11 +424,25 @@ Currently Nikola emits the following signals: 'undeployed': # all files not deployed since they are either future posts/drafts } +ConfigPlugin Plugins +-------------------- + +Does nothing specific, can be used to modify the site object (and thus the config). + +Put all the magic you want in ``set_site()``, and don’t forget to run the one +from ``super()``. + +PostScanner Plugins +------------------- + +Get posts and stories from "somewhere" to be added to the timeline. +The only currently existing plugin of this kind reads them from disk. + Plugin Index ============ -There is a `plugin index <http://plugins.getnikola.com/>`__, which stores all +There is a `plugin index <https://plugins.getnikola.com/>`__, which stores all of the plugins for Nikola people wanted to share with the world. You may want to read the `README for the Index diff --git a/docs/internals.txt b/docs/internals.txt index a025075..448a6f7 100644 --- a/docs/internals.txt +++ b/docs/internals.txt @@ -26,7 +26,7 @@ Nikola is a Pile of Plugins There are several kinds of plugins, all implementing interfaces defined in ``nikola/plugin_categories.py`` and documented in - `Extending Nikola <http://getnikola.com/extending.html>`_ + `Extending Nikola <https://getnikola.com/extending.html>`_ If your plugin has a dependency, please make sure it doesn't make Nikola throw an exception when the dependency is missing. Try to fail gracefully @@ -95,17 +95,14 @@ posts are added into RSS feeds and stories are not. All of them are in a list ca "the timeline" formed by objects of class ``Post``. When you are creating a task that needs the list of posts and/or stories (for example, -the RSS creation plugin), your plugin should call ``self.site.scan_posts()`` to ensure -the timeline is created and available in ``self.site.timeline``. You should not modify -the timeline, because it will cause consistency issues. +the RSS creation plugin) on task execution time, your plugin should call ``self.site.scan_posts()`` +in ``gen_tasks`` to ensure the timeline is created and available in +``self.site.timeline``. You should not modify the timeline, because it will cause consistency issues. .. sidebar:: scan_posts - The scan_posts function is what reads your site and creates the timeline. - - I am considering moving scan_posts off the core and into its own plugin - so it can be replaced (for example, by a version that reads a database - instead of scanning a folder tree). + The ``Nikola.scan_posts`` function can be used in plugins to force the + timeline creation, for example, while creating the tasks. Your plugin can use the timeline to generate "stuff" (technical term). For example, Nikola comes with plugins that use the timeline to create a website (surprised?). @@ -140,3 +137,8 @@ themes To change how the generated site looks, you can create custom themes. And of course, you can also replace or extend each of the existing plugins. + +Nikola Architecture +=================== + +.. thumbnail:: https://getnikola.com/images/architecture.png diff --git a/docs/man/nikola.1 b/docs/man/nikola.1 deleted file mode 100644 index a0c2c05..0000000 --- a/docs/man/nikola.1 +++ /dev/null @@ -1,91 +0,0 @@ -.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.44.1. -.TH NIKOLA "1" "September 2014" "nikola 7.1.0" "User Commands" -.SH NAME -nikola \- manual page for nikola 7.1.0 -.SH DESCRIPTION -Nikola is a tool to create static websites and blogs. For full documentation and more information, please visit http://getnikola.com/ -.SS "Available commands:" -.TP -nikola auto -automatically detect site changes, rebuild and optionally refresh a browser -.TP -nikola bootswatch_theme -given a swatch name from bootswatch.com and a parent theme, creates a custom theme -.TP -nikola build -run tasks -.TP -nikola check -check links and files in the generated site -.TP -nikola clean -clean action / remove targets -.TP -nikola console -start an interactive Python console with access to your site -.TP -nikola deploy -deploy the site -.TP -nikola doit_auto -automatically execute tasks when a dependency changes -.TP -nikola dumpdb -dump dependency DB -.TP -nikola forget -clear successful run status from internal DB -.TP -nikola github_deploy -deploy the site to GitHub pages -.TP -nikola help -show help -.TP -nikola ignore -ignore task (skip) on subsequent runs -.TP -nikola import_wordpress -import a WordPress dump -.TP -nikola init -create a Nikola site in the specified folder -.TP -nikola install_theme -install theme into current site -.TP -nikola list -list tasks from dodo file -.TP -nikola new_page -create a new page in the site -.TP -nikola new_post -create a new blog post or site page -.TP -nikola orphans -list all orphans -.TP -nikola plugin -manage plugins -.TP -nikola serve -start the test webserver -.TP -nikola strace -use strace to list file_deps and targets -.TP -nikola tabcompletion -generate script for tab\-complention -.TP -nikola version -print the Nikola version number -.TP -nikola help -show help / reference -.TP -nikola help <command> -show command usage -.TP -nikola help <task\-name> -show task usage diff --git a/docs/man/nikola.1.gz b/docs/man/nikola.1.gz Binary files differnew file mode 100644 index 0000000..e2425f4 --- /dev/null +++ b/docs/man/nikola.1.gz diff --git a/docs/man/nikola.rst b/docs/man/nikola.rst new file mode 100644 index 0000000..036170d --- /dev/null +++ b/docs/man/nikola.rst @@ -0,0 +1,118 @@ +====== +Nikola +====== + +-------------------------------- +A Static Site and Blog Generator +-------------------------------- + +:Version: Nikola v7.6.0 +:Manual section: 1 +:Manual group: User Commands + +SYNOPSIS +======== + +Create an empty site (with a setup wizard): + + ``nikola init mysite`` + +(You can create a site with demo files in it with ``nikola init --demo mysite``) + +Create a post (inside the ``mysite`` directory): + + ``nikola new_post`` + +Build the site: + + ``nikola build`` + +Start the test server and open a browser: + + ``nikola serve -b`` + + +DESCRIPTION +=========== + +Nikola is a static website and blog generator. The very short +explanation is that it takes some texts you wrote, and uses them to +create a folder full of HTML files. If you upload that folder to a +server, you will have a rather full-featured website, done with little +effort. + +Its original goal is to create blogs, but it supports most kind of +sites, and can be used as a CMS, as long as what you present to the +user is your own content instead of something the user generates. + +Nikola can do: + +* A blog +* Your company's site +* Your personal site +* A software project's site +* A book's site + +Since Nikola-based sites don't run any code on the server, there is no +way to process user input in forms. + +Nikola can't do: + +* Twitter +* Facebook +* An Issue tracker +* Anything with forms, really (except for comments!) + +Keep in mind that "static" doesn't mean **boring**. You can have +animations, slides or whatever fancy CSS/HTML5 thingie you like. It +only means all that HTML is generated already before being uploaded. +On the other hand, Nikola sites will tend to be content-heavy. What +Nikola is good at is at putting what you write out there. + +COMMANDS +======== + +The most basic commands needed to get by are: + +``nikola help`` + get a list of commands, or help for a command +``nikola version [--check]`` + print version number +``nikola init [-d|--demo] [-q|--quiet] folder`` + initialize new site +``nikola build`` + build a site +``nikola new_post`` + create a new post +``nikola new_page`` + create a new page +``nikola status [--list-drafts] [--list-modified] [--list-scheduled]`` + show site and deployment status +``nikola check [-v] (-l [--find-sources] [-r] | -f [--clean-files])`` + check for dangling links or unknown files +``nikola deploy [[preset [preset...]]`` + deploy the site using the ``DEPLOY_COMMANDS`` setting +``nikola github_deploy``` + deploy the site to GitHub Pages +``nikola serve [-p PORT] [-a ADDRESS] [-b|--browser] [-6|--ipv6]`` + start development web server +``nikola auto [-p PORT] [-a ADDRESS] [-b|--browser] [-6|--ipv6]`` + start development web server with automated rebuilds and reloads +``nikola plugin [options]`` + manage plugins from the Plugins Index (https://plugins.getnikola.com/) +``nikola install_theme [name]`` + install themes from the Themes Index (https://themes.getnikola.com/) + +Use ``nikola help`` to get a list of all commands. + +BUGS +==== + +Issue Tracker: https://github.com/getnikola/nikola/issues + +SEE ALSO +======== + +* The Nikola Website: https://getnikola.com/ +* Handbook: https://getnikola.com/handbook.html +* Support: https://getnikola.com/contact.html diff --git a/docs/manual.txt b/docs/manual.txt index 3917dbc..d287099 100644 --- a/docs/manual.txt +++ b/docs/manual.txt @@ -1,14 +1,13 @@ .. title: The Nikola Handbook .. slug: handbook .. date: 2012-03-30 23:00:00 UTC-03:00 -.. tags: mathjax .. link: .. description: The Nikola Handbook =================== -:Version: 7.1.0 +:Version: 7.6.0 .. class:: alert alert-info pull-right @@ -20,7 +19,7 @@ All You Need to Know After you have Nikola `installed <#installing-nikola>`_: -Create a empty site (with a setup wizard): +Create an empty site (with a setup wizard): ``nikola init mysite`` You can create a site with demo files in it with ``nikola init --demo mysite`` @@ -32,15 +31,14 @@ Create a post: Edit the post: The filename should be in the output of the previous command. + You can also use ``nikola new_post -e`` to open an editor automatically. Build the site: ``nikola build`` -Start the test server: - ``nikola serve`` +Start the test server and open a browser (http://127.0.0.1:8000/): + ``nikola serve -b`` -See the site: - http://127.0.0.1:8000 That should get you going. If you want to know more, this manual will always be here for you. @@ -58,7 +56,7 @@ that it takes some texts you wrote, and uses them to create a folder full of HTML files. If you upload that folder to a server, you will have a rather full-featured website, done with little effort. -It's original goal is to create blogs, but it supports most kind of sites, and +Its original goal is to create blogs, but it supports most kind of sites, and can be used as a CMS, as long as what you present to the user is your own content instead of something the user generates. @@ -67,7 +65,7 @@ Nikola can do: * A blog (`example <http://ralsina.me>`__) * Your company's site * Your personal site -* A software project's site (`example <http://getnikola.com>`__) +* A software project's site (`example <https://getnikola.com>`__) * A book's site Since Nikola-based sites don't run any code on the server, there is no way to process @@ -91,13 +89,13 @@ Getting Help .. class:: lead -`Get help here! <http://getnikola.com/contact.html>`_ +`Get help here! <https://getnikola.com/contact.html>`_ TL;DR: * You can file bugs at `the issue tracker <https://github.com/getnikola/nikola/issues>`__ * You can discuss Nikola at the `nikola-discuss google group <http://groups.google.com/group/nikola-discuss>`_ -* You can subscribe to `the Nikola Blog <http://getnikola.com/blog>`_ +* You can subscribe to `the Nikola Blog <https://getnikola.com/blog>`_ * You can follow `Nikola on Twitter <https://twitter.com/GetNikola>`_ Why Static? @@ -136,7 +134,7 @@ Obsolescense You may say those are long term issues, or that they won't matter for years. Well, I believe things should work forever, or as close to it as we can make them. Nikola's static output and its input files will work as long as you can install - a Python > 2.6 in a Linux, Windows, or Mac and can find a server + a Python 2.7/3.3 or newer under Linux, Windows, or OS X and can find a server that sends files over HTTP. That's probably 10 or 15 years at least. Also, static sites are easily handled by the Internet Archive. @@ -180,7 +178,7 @@ If you want to create a blog or a site, Nikola provides: * Google sitemap generation * Custom deployment (if it's a command, you can use it) * A (very) basic look and feel you can customize, and is even text-mode friendly -* The input format is light markup (`reStructuredText <http://getnikola.com/quickstart.html>`__ or +* The input format is light markup (`reStructuredText <https://getnikola.com/quickstart.html>`__ or `Markdown <http://daringfireball.net/projects/markdown/>`_) * Easy-to-create image galleries * Support for displaying source code @@ -205,7 +203,7 @@ The short version is:: pip install nikola -Note that you need Python v2.6 or newer OR v3.3 or newer. +Note that you need Python v2.7 or newer OR v3.3 or newer. Some features require **extra dependencies**. You can install them all in bulk by doing:: @@ -219,31 +217,41 @@ After that, run ``nikola init --demo sitename`` and that will run the setup wizard, which will create a folder called ``sitename`` containing a functional demo site. -Nikola is packaged for some Linux distributions, you may get that instead. e.g. -If you are running Arch Linux, there are AUR packages, available in Python 2/3 -and stable/git master flavors: `python-nikola`__ / `python2-nikola`__ for the -latest stable release or `python-nikola-git`__ / `python2-nikola-git`__ for the -GitHub master. (only one package may be installed at the same time.) +Linux packages +~~~~~~~~~~~~~~ + +Nikola is packaged for some Linux distributions, you may get that instead of +installing via ``pip``. Keep in mind that those packages might be +**outdated** and that we don’t support versions that are too old. Proceed with +care! + +* Arch Linux (AUR): `python-nikola`__ / `python2-nikola`__ for the + latest stable release or `python-nikola-git`__ / `python2-nikola-git`__ for the + GitHub master. (official Nikola-supported packages) +* Fedora: `python-nikola`__ (incl. python3-nikola) +* Debian and derivatives: `nikola`__ +* Gentoo: `www-apps/nikola`__ __ https://aur.archlinux.org/packages/python-nikola/ __ https://aur.archlinux.org/packages/python2-nikola/ __ https://aur.archlinux.org/packages/python-nikola-git/ __ https://aur.archlinux.org/packages/python2-nikola-git/ +__ https://admin.fedoraproject.org/pkgdb/package/python-nikola/ +__ https://packages.debian.org/sid/nikola +__ https://packages.gentoo.org/package/www-apps/nikola -libxml/libxslt errors -~~~~~~~~~~~~~~~~~~~~~ +libxml/libxslt (files missing) errors +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If you get a ``ERROR: /bin/sh: 1: xslt-config: not found`` or ``fatal error: -libxml/xmlversion.h: No such file or directory`` when running ``pip install -r requirements.txt``, install *libxml* and *libxslt* libraries, like so: +If you get errors about various files missing while compiling ``lxml``, you must install headers for the ``libxml``, ``libxslt`` and ``zlib`` libraries, like so: Debian systems:: - sudo apt-get install libxml2-dev - sudo apt-get install libxslt1-dev + sudo apt-get install libxml2-dev libxslt1-dev zlib1g-dev Red Hat/RPM-based systems:: - sudo yum install libxslt-devel libxml2-devel + sudo yum install libxslt-devel libxml2-devel zlib-devel Python.h not found ~~~~~~~~~~~~~~~~~~ @@ -263,18 +271,6 @@ Note that many other distros/operating systems (including Arch Linux, \*BSD and OS X) do not require such packages, as C headers are included with the base distribution of Python. -Installation on Linux, Mac OS X, \*BSD, and any other POSIX-compatible OS -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -(we obviously support all.) - -Using ``pip`` should suffice. You may also want to use distribution- or -system-specific packages for our dependencies. - -There are **no known issues or caveats** on those OSes. Keep in mind that most -of our developers run Linux on a daily basis and may not have the full -knowledge required to resolve issues relating to your operating system. - Installation on Windows and Windows support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -289,7 +285,7 @@ caveats: pre-built packages is possible through ``virtualenv --system-site-packages``. #. Windows has some differences over POSIX, which may cause some features to work incorrectly under Windows. If any problems occur, please do not - hesitate to report them. Some of the differeces include: + hesitate to report them. Some of the differences include: * ``\`` as path separator (instead of ``/``) * the concept of HDD partitions and letters (instead of @@ -307,9 +303,10 @@ Getting Started To create posts and pages in Nikola, you write them in one of the supported input formats. Those source files are later converted to HTML The recommended formats are reStructuredText and Markdown, but there is also support -for textile and WikiCreole and even for just writing HTML. +for Textile and WikiCreole and even for just writing HTML. For more details, +read `Configuring other input formats`_. -.. note:: There is a great `quick tutorial to learn reStructuredText. <http://getnikola.com/quickstart.html>`__ +.. note:: There is a great `quick tutorial to learn reStructuredText. <https://getnikola.com/quickstart.html>`__ First, let's see how you "build" your site. Nikola comes with a minimal site to get you started. @@ -373,7 +370,7 @@ and even individual files like ``nikola build output/index.html`` Nikola also has other commands besides ``build``:: $ nikola help - Nikola is a tool to create static websites and blogs. For full documentation and more information, please visit http://getnikola.com/ + Nikola is a tool to create static websites and blogs. For full documentation and more information, please visit https://getnikola.com/ Available commands: @@ -400,7 +397,7 @@ Nikola also has other commands besides ``build``:: nikola plugin manage plugins nikola serve start the test webserver nikola strace use strace to list file_deps and targets - nikola tabcompletion generate script for tab-complention + nikola tabcompletion generate script for tab-completion nikola version print the Nikola version number nikola help show help / reference @@ -440,7 +437,8 @@ but you can use a lot of different markups using the ``-f`` option. Currently Nikola supports reStructuredText, Markdown, IPython Notebooks, HTML as input, can also use Pandoc for conversion, and has support for BBCode, CreoleWiki, txt2tags, Textile -and more via `plugins <http://plugins.getnikola.com>`__. +and more via `plugins <https://plugins.getnikola.com>`__. +For more details, read `Configuring other input formats`_. You can control what markup compiler is used for each file extension with the ``COMPILERS`` option. The default configuration expects them to be placed in ``posts`` but that can be @@ -493,11 +491,47 @@ to your configuration:: Nikola will also use other metadata fields: + author + Author of the post, will be used in the RSS feed and possibly in the post + display (theme-dependent) + + annotations / noannotations + Override the value of the ``ANNOTATIONS`` option for this specific post or page. + + category + Like tags, except each post can have only one, and they usually have + more descriptive names. + + filters + See the `Post Processing Filters`_ section. + + hidetitle + Set "True" if you do not want to see the **page** title as a + heading of the output html file (does not work for posts). + nocomments Set to "True" to disable comments. Example:: .. nocomments: True + password + The post will be encrypted and invisible until the reader enters the password. + Also, the post's sourcecode will not be available. + + WARNING: **DO NOT** use for real confidential data. The algorithm used (RC4) is insecure. The implementation may also be easily brute-forced. Please consider using something else if you need *real* encryption! + + More information: `Issue #1547 <https://github.com/getnikola/nikola/issues/1547>`_ + + previewimage + Designate a preview or other representative image path relative to BASE_URL + for use with Open Graph for posts. Adds the image when sharing on social + media and many other uses. + + .. previewimage: images/looks_great_on_facebook.png + + The image can be of any size and dimension (services will crop and adapt) + but should less than 1 MB and be larger than 300x300 (ideally 600x600). + template Will change the template used to render this page/post specific page. Example:: @@ -506,24 +540,8 @@ to your configuration:: That template needs to either be part of the theme, or be placed in a ``templates/`` folder inside your site. - password - The post will be encrypted and invisible until the reader enters the password. - Also, the post's sourcecode will not be available. - - category - Like tags, except each post can have only one, and they usually have - more descriptive names. - - annotations / noannotations - Override the value of the ``ANNOTATIONS`` option for this specific post or page. - - author - Author of the post, will be used in the RSS feed and possibly in the post - display (theme-dependent) - - hidetitle - Set "True" if you do not want to see the **story** title as a - heading of the page (does not work for posts). + enclosure + Add an enclosure to this post when it's used in RSS. See `more information about enclosures <http://en.wikipedia.org/wiki/RSS_enclosure>`__ .. note:: The Two-File Format @@ -603,7 +621,7 @@ Currently supported languages are: * Urdu If you wish to add support for more languages, check out the instructions -at the `theming guide <http://getnikola.com/theming.html>`_. +at the `theming guide <https://getnikola.com/theming.html>`_. The post page is generated using the ``post.tmpl`` template, which you can use to customize the output. @@ -625,7 +643,7 @@ and ``PAGES`` configuration options:: # From those files, a set of HTML fragment files will be generated: # cache/whatever/thing.html (and maybe cache/whatever/thing.html.es) # - # These files are combinated with the template to produce rendered + # These files are combined with the template to produce rendered # pages, which will be placed at # output / TRANSLATIONS[lang] / destination / pagename.html # @@ -647,7 +665,7 @@ and ``PAGES`` configuration options:: ``new_post`` will use the *first* path in ``POSTS`` (or ``PAGES`` if ``-p`` is supplied) that ends with the extension of your desired markup format (as -defined in ``COMPILERS`` in conf.py) as the directory that the new post will be +defined in ``COMPILERS`` in ``conf.py``) as the directory that the new post will be written into. If no such entry can be found, the post won’t be created. The ``new_post`` command supports some options:: @@ -680,7 +698,7 @@ In reStructuredText:: .. TEASER_END -In Markdown:: +In Markdown (or basically, the resulting HTML of any format):: <!-- TEASER_END --> @@ -712,10 +730,11 @@ Drafts If you add a "draft" tag to a post, then it will not be shown in indexes and feeds. It *will* be compiled, and if you deploy it it *will* be made available, so use with care. If you wish your drafts to be not available in your deployed site, you -can set ``DEPLOY_DRAFTS = False`` in your configuration. +can set ``DEPLOY_DRAFTS = False`` in your configuration. This will not work if +lazily include ``nikola build`` in your ``DEPLOY_COMMANDS``. Also if a post has a date in the future, it will not be shown in indexes until -you rebuild after that date. This behaviour can be disabled by setting +you rebuild after that date. This behavior can be disabled by setting ``FUTURE_IS_NOW = True`` in your configuration, which will make future posts be published immediately. Posts dated in the future are *not* deployed by default (when ``FUTURE_IS_NOW = False``). To make future posts available in the @@ -786,6 +805,120 @@ styles the following types in the default themes: | micro | “small” (short) posts | big serif font | +-----------------+----------------------------+------------------+ +Configuring other input formats +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In order to use input formats other than reStructuredText, you need some extra +setup. + +1. Make sure you have the compiler for the input format you want. Some + input formats are supported out-of-the-box, but others must be installed from + the Plugins repository. You may also need some extra dependencies. You + will get helpful errors if you try to build when missing something. +2. You must ensure the compiler and your desired input file extension is included + in the ``COMPILERS`` dict and does not conflict with any other format. This + is extremely important for the pandoc compiler. +3. Finally, you must configure the ``POSTS`` and ``PAGES`` tuples. Follow the + instructions and the format set by pre-existing entries. Make sure to use + the same extension as is set in ``COMPILERS`` and configure the outputs + properly. + +Markdown +```````` + +To use Markdown in your posts/pages, make sure ``markdown`` is in your +``COMPILERS`` and that at least one of your desired extensions is defined in +``POSTS`` and ``PAGES``. + +You can use Python-Markdown extensions by setting the ``MARKDOWN_EXTENSIONS`` +config option: + +.. code:: python + + MARKDOWN_EXTENSIONS = ['fenced_code', 'codehilite', 'extra'] + +IPython Notebook/Jupyter +```````````````````````` + +To use Jupyter notebooks (previously known as IPython Notebooks) as posts/pages, +make sure ``ipynb`` is in your ``COMPILERS`` and that the ``.ipynb`` extension +is defined in ``POSTS`` and ``PAGES``. + +The ``-f`` argument to ``new_post`` should be used in the ``ipynb@KERNEL`` format. +It defaults to Python in the version used by Nikola if not specified. + +HTML +```` + +To use plain HTML in your posts/pages, make sure ``html`` is in your +``COMPILERS`` +and that the ``.html`` extension is defined in ``POSTS`` and ``PAGES``. + +PHP +``` + +There are two ways of using PHP within Nikola: + +1. To use PHP in your posts/pages (inside your site, with the theme and + everything), make sure ``php`` is in your ``COMPILERS`` and that the ``.php`` + extension is defined in ``POSTS`` and ``PAGES``. +2. To use PHP as standalone files (without any modifications), put them in + ``files/`` (or whatever ``FILES_FOLDERS`` is configured to). + +Pandoc +`````` + +To use Pandoc, you must uncomment the entry in ``COMPILERS`` and set the +extensions list to your desired extensions while also removing them from their +original compilers. The input format is inferred from the extension by Pandoc. + +Using Pandoc for reStructuredText, Markdown and other input formats that have a +standalone Nikola plugin is **not recommended** as it disables plugins and +extensions that are usually provided by Nikola. + +Indexes +~~~~~~~ + +All your posts that are not drafts, private or dated in the future, will be +shown in indexes. + +Settings +```````` + +Indexes are put in the ``INDEX_PATH`` directory, which defaults to an empty +string (site root). The “main” index is ``index.html``, and all the further +indexes are ``index-*.html``, respectively. + +By default, 10 posts are displayed on an index page. This can be changed with +``INDEX_DISPLAY_POST_COUNT``. Indexes can show full posts or just the teasers, +as controlled by the ``INDEX_TEASERS`` setting (defaults to ``False``). + +Titles of the pages can be controlled by using ``INDEXES_TITLES``, +``INDEXES_PAGES`` and ``INDEXES_PAGES_MAIN`` settings. + +Categories and tags use simple lists by default that show only titles and +dates; however, you can switch them to full indexes by using +``CATEGORY_PAGES_ARE_INDEXES`` and ``TAG_PAGES_ARE_INDEXES``, respectively. + +Static indexes +`````````````` + +Nikola uses *static indexes* by default. This means that ``index-1.html`` has +the oldest posts, and the newest posts past the first 10 are in +``index-N.html``, where ``N`` is the highest number. Only the page with the +highest number and the main page (``index-N.html`` and ``index.html``) are +rebuilt (the others remain unchanged). The page that appears when you click +*Older posts* on the index page, ``index-N.html``, might contain **less than 10 +posts** if there are not enough posts to fill up all pages. + +This can be disabled by setting ``INDEXES_STATIC`` to ``False``. In that mode, +``index-1.html`` contains all the newest posts past the first 10 and will +always contain 10 posts (unless you have less than 20). The last page, +``index-N.html``, contains the oldest posts, and might contain less than 10 +posts. This is how many blog engines and CMSes behave. Note that this will +lead to rebuilding all index pages, which might be a problem for larger blogs +(with a lot of index pages). + Creating a Page --------------- @@ -836,7 +969,7 @@ You surely want to edit these options:: # Data about this site BLOG_AUTHOR = "Your Name" # (translatable) BLOG_TITLE = "Demo Site" # (translatable) - SITE_URL = "http://getnikola.com/" + SITE_URL = "https://getnikola.com/" BLOG_EMAIL = "joe@demo.site" BLOG_DESCRIPTION = "This is a demo site for Nikola." # (translatable) @@ -846,6 +979,11 @@ them. For those options, two types of values can be provided: * a string, which will be used for all languages * a dict of language-value pairs, to have different values in each language +.. note:: It is possible to load the configuration from another file by specifying + ``--conf=path/to/other.file`` on Nikola's command line. For example, to + build your blog using the configuration file ``configurations/test.config``, + you have to execute ``nikola build --conf=configurations/test.config``. + Customizing Your Site --------------------- @@ -854,17 +992,17 @@ the easy ones! CSS tweaking Using the default configuration, you can create a ``assets/css/custom.css`` - file and then it will be loaded from the ``<head>`` blocks of your site - pages. Create it and put your CSS code there, for minimal disruption of the - provided CSS files. + file under ``files/`` or in your theme and then it will be loaded from the + ``<head>`` blocks of your site pages. Create it and put your CSS code there, + for minimal disruption of the provided CSS files. If you feel tempted to touch other files in assets, you probably will be better off with a `custom theme <theming.html>`__. If you want to use LESS_ or Sass_ for your custom CSS, or the theme you use contains LESS or Sass code that you want to override, you will need to install - the `LESS plugin <http://plugins.getnikola.com/#less>`__ or - `SASS plugin <http://plugins.getnikola.com/#sass>`__ create a ``less`` or + the `LESS plugin <https://plugins.getnikola.com/#less>`__ or + `SASS plugin <https://plugins.getnikola.com/#sass>`__ create a ``less`` or ``sass`` directory in your site root, put your ``.less`` or ``.scss`` files there and a targets file containing the list of files you want compiled. @@ -904,10 +1042,17 @@ Navigation Links submenus is supported. .. note:: + Some themes, including the default Bootstrap 3 theme, may present issues if the menu is too large. (in ``bootstrap3``, the navbar can grow too large and cover contents.) + .. note:: + + If you link to directories, make sure to follow ``STRIP_INDEXES``. If + it’s set to ``True``, end your links with a ``/``, otherwise end them + with ``/index.html`` — or else they won’t be hilighted when active. + The ``SEARCH_FORM`` option contains the HTML code for a search form based on duckduckgo.com which should always work, but feel free to change it to something else. @@ -929,6 +1074,60 @@ SOCIAL_BUTTONS_CODE at the bottom of body. It defaults to a snippet for AddThis, but you can really put anything there. See `social_buttons.html` for more details. +Fancy Dates +----------- + +Nikola can use various styles for presenting dates. + +DATE_FORMAT + The date format to use if there is no JS or fancy dates are off. Compatible with Python’s ``strftime()`` syntax. + +JS_DATE_FORMAT + The date format to use if fancy dates are on. Compatible with ``moment.js`` syntax. + +DATE_FANCINESS = 0 + Fancy dates are off, and DATE_FORMAT is used. + +DATE_FANCINESS = 1 + Dates are recalculated in user’s timezone. Requires JavaScript. + +DATE_FANCINESS = 2 + Dates are recalculated as relative time (eg. 2 days ago). Requires JavaScript. + +In order to use fancy dates, your theme must support them. The built-in Bootstrap family supports it, but other themes might not by default. + +For Mako: + +.. code:: html + + <!-- required scripts -- best handled with bundles --> + <script src="/assets/js/moment-with-locales.min.js"></script> + <script src="/assets/js/fancydates.js"></script> + + <!-- fancy dates code --> + <script> + moment.locale("${momentjs_locales[lang]}"); + fancydates(${date_fanciness}, ${js_date_format}); + </script> + <!-- end fancy dates code --> + + +For Jinja2: + +.. code:: html + + <!-- required scripts -- best handled with bundles --> + <script src="/assets/js/moment-with-locales.min.js"></script> + <script src="/assets/js/fancydates.js"></script> + + <!-- fancy dates code --> + <script> + moment.locale("{{ momentjs_locales[lang] }}"); + fancydates({{ date_fanciness }}, {{ js_date_format }}); + </script> + <!-- end fancy dates code --> + + Adding Files ------------ @@ -955,7 +1154,7 @@ Getting More Themes ------------------- There are a few themes for Nikola. They are available at -the `Themes Index <http://themes.getnikola.com/>`_. +the `Themes Index <https://themes.getnikola.com/>`_. Nikola has a built-in theme download/install mechanism to install those themes — the ``install_theme`` command:: $ nikola install_theme -l @@ -968,7 +1167,7 @@ Nikola has a built-in theme download/install mechanism to install those themes $ nikola install_theme blogtxt [2013-10-12T16:46:13Z] NOTICE: install_theme: Downloading: - http://themes.getnikola.com/v6/blogtxt.zip + https://themes.getnikola.com/v6/blogtxt.zip [2013-10-12T16:46:15Z] NOTICE: install_theme: Extracting: blogtxt into themes And there you are, you now have themes/blogtxt installed. It's very @@ -1003,27 +1202,32 @@ Nikola doesn't really have a concept of deployment. However, if you can specify deployment procedure as a series of commands, you can put them in the ``DEPLOY_COMMANDS`` option, and run them with ``nikola deploy``. +You can have multiple deployment presets. If you run ``nikola deploy``, the +``default`` preset is executed. You can also specify the names of presets +you want to run (eg. ``nikola deploy default``, multiple presets are allowed). + One caveat is that if any command has a % in it, you should double them. Here is an example, from my own site's deployment script:: - DEPLOY_COMMANDS = [ + DEPLOY_COMMANDS = {'default': [ 'rsync -rav --delete output/ ralsina@lateral.netmanagers.com.ar:/srv/www/lateral', 'rdiff-backup output ~/blog-backup', "links -dump 'http://www.twingly.com/ping2?url=lateral.netmanagers.com.ar'", - ] + ]} Other interesting ideas are using `git as a deployment mechanism <http://toroid.org/ams/git-website-howto>`_ (or any other VCS -for that matter), using `lftp mirror <http://lftp.yar.ru/>`_ or unison, or Dropbox, or -Ubuntu One. Any way you can think of to copy files from one place to another is good enough. +for that matter), using `lftp mirror <http://lftp.yar.ru/>`_ or unison, or Dropbox. +Any way you can think of to copy files from one place to another is good enough. Deploying to GitHub ~~~~~~~~~~~~~~~~~~~ -Nikola provides a separate command ``github_deploy`` to deploy your -site to GitHub pages. The command builds the site, commits the -output to a gh-pages branch and pushes the output to GitHub. +Nikola provides a separate command ``github_deploy`` to deploy your site to +GitHub pages. The command builds the site, commits the output to a gh-pages +branch and pushes the output to GitHub. Nikola uses the `ghp-import command +<https://github.com/davisp/ghp-import>`_ for this. The branch to use for committing the sources can be changed using the ``GITHUB_DEPLOY_BRANCH`` option in your config. For a @@ -1037,14 +1241,9 @@ push to the repository specified as the remote. This command performs the following actions, when it is run: -1. Ensure that your site is a git repository, and git is on the PATH. -2. Check for changes, and prompt the user to continue, if required. -3. Build the site -4. Clean any files that are "unknown" to Nikola. -5. Create a deploy branch, if one doesn't exist. -6. Commit the output to this branch. (NOTE: Any untracked source - files, may get committed at this stage, on the wrong branch!) -7. Push and deploy! +1. Builds the site +2. Commit the output folder to the ``GITHUB_DEPLOY_BRANCH`` to this branch. +3. Push the branch to the remote specified in ``GITHUB_REMOTE_NAME``! Comments and Annotations ------------------------ @@ -1063,8 +1262,8 @@ Nikola supports several third party comment systems: * `isso <http://posativ.org/isso/>`_ By default it will use DISQUS, but you can change by setting ``COMMENT_SYSTEM`` -to one of "disqus", "intensedebate", "livefyre", "moot", "googleplus" or -"facebook" +to one of "disqus", "intensedebate", "livefyre", "moot", "googleplus", +"facebook" or "isso" .. sidebar:: ``COMMENT_SYSTEM_ID`` @@ -1080,7 +1279,8 @@ to one of "disqus", "intensedebate", "livefyre", "moot", "googleplus" or * For Facebook, you need to `create an app <https://developers.facebook.com/apps>` (turn off sandbox mode!) and get an **App ID** - * For isso, it is the URL of isso (must be world-accessible and **have a trailing slash**, + * For isso, it is the URL of isso (must be world-accessible, encoded with + Punycode (if using Internationalized Domain Names) and **have a trailing slash**, default ``http://localhost:8080/``) To use comments in a visible site, you should register with the service and @@ -1126,7 +1326,7 @@ You can disable comments for a post by adding a "nocomments" metadata field to i #639). An alternative or complement to comments are annotations. Nikola integrates -the annotation service provided by `AnnotateIt. <annotateit.org>`_ +the annotation service provided by `AnnotateIt. <http://annotateit.org/>`_ To use it, set the ``ANNOTATIONS`` option to True. This is specially useful if you want feedback on specific parts of your writing. @@ -1137,30 +1337,53 @@ Annotations require JQuery and are therefore not supported in the base theme. You can check bootstrap theme's ``base.html`` for details on how to handle them in custom themes. -Image Galleries ---------------- +Images and Galleries +-------------------- To create an image gallery, all you have to do is add a folder inside ``galleries``, and put images there. Nikola will take care of creating thumbnails, index page, etc. -If you click on images on a gallery, you should see a bigger image, thanks to -the excellent `colorbox <http://www.jacklmoore.com/colorbox>`_ +If you click on images on a gallery, or on images with links in post, you will +see a bigger image, thanks to the excellent `colorbox +<http://www.jacklmoore.com/colorbox>`_. If don’t want this behavior, add an +``.islink`` class to your image or link. The gallery pages are generated using the ``gallery.tmpl`` template, and you can customize it there (you could switch to another lightbox instead of colorbox, change its settings, change the layout, etc.). -The ``conf.py`` options affecting gallery pages are these:: +Images to be used in normal posts can be placed in the ``images`` folder. These +images will be processed and have thumbnails created just as for galleries, but will +then be copied directly to the corresponding path in the ``output`` directory, so you +can reference it from whatever page you like, most easily using the ``thumbnail`` +reST extension. If you don't want thumbnails, just use the ``files`` folder instead. + +The ``conf.py`` options affecting images and gallery pages are these:: - # Galleries are folders in galleries/ - # Final location of galleries will be output / GALLERY_PATH / gallery_name - GALLERY_PATH = "galleries" + # One or more folders containing galleries. The format is a dictionary of + # {"source": "relative_destination"}, where galleries are looked for in + # "source/" and the results will be located in + # "OUTPUT_PATH/relative_destination/gallery_name" + # Default is: + GALLERY_FOLDERS = {"galleries": "galleries"} + # More gallery options: THUMBNAIL_SIZE = 180 MAX_IMAGE_SIZE = 1280 USE_FILENAME_AS_TITLE = True - GALLERY_SORT_BY_DATE = False EXTRA_IMAGE_EXTENSIONS = [] + # If set to False, it will sort by filename instead. Defaults to True + GALLERY_SORT_BY_DATE = True + + # Folders containing images to be used in normal posts or pages. Images will be + # scaled down according to IMAGE_THUMBNAIL_SIZE and MAX_IMAGE_SIZE options, but + # will have to be referenced manually to be visible on the site + # (the thumbnail has ``.thumbnail`` added before the file extension). + # The format is a dictionary of {source: relative destination}. + + IMAGE_FOLDERS = {'images': 'images'} + IMAGE_THUMBNAIL_SIZE = 400 + If you add a file in ``galleries/gallery_name/index.txt`` its contents will be converted to HTML and inserted above the images in the gallery page. The format is the same as for posts. @@ -1212,20 +1435,50 @@ The currently available filters are: def yui_compressor(infile): return runinplace(r'yui-compressor --nomunge %1 -o %2', infile) - You can turn any function into a filter using ``apply_to_file``. + You can turn any function into a filter using ``apply_to_text_file`` (for + text files to be read in UTF-8) and ``apply_to_binary_file`` (for files to + be read in binary mode). + As a silly example, this would make everything uppercase and totally break your website: .. code-block:: python import string - from nikola.filters import apply_to_file + from nikola.filters import apply_to_text_file FILTERS = { - ".html": [apply_to_file(string.upper)] + ".html": [apply_to_text_file(string.upper)] } +html_tidy_nowrap + Prettify HTML 5 documents with `tidy5 <http://www.html-tidy.org/>`_ + +html_tidy_wrap + Prettify HTML 5 documents wrapped at 80 characters with `tidy5 <http://www.html-tidy.org/>`_ + +html_tidy_wrap_attr + Prettify HTML 5 documents and wrap lines and attributes with `tidy5 <http://www.html-tidy.org/>`_ + +html_tidy_mini + Minify HTML 5 into smaller documents with `tidy5 <http://www.html-tidy.org/>`_ + +html_tidy_withconfig + Run `tidy5 <http://www.html-tidy.org/>`_ with ``tidy5.conf`` as the config file (supplied by user) + +html5lib_minify + Minify HTML5 using html5lib_minify + +html5lib_xmllike + Format using html5lib + +typogrify + Improve typography using `typogrify <http://static.mintchaos.com/projects/typogrify/>`__ + +typogrify_sans_widont + Same as typogrify without the widont filter + minify_lines - Strips leading whitespace and blank lines. Useful for compacting HTML but pre-formatted text must be escaped manually. + **THIS FILTER HAS BEEN TURNED INTO A NOOP** and currently does nothing. yui_compressor Compress CSS/JavaScript using `YUI compressor <http://yui.github.io/yuicompressor/>`_ @@ -1239,8 +1492,11 @@ optipng jpegoptim Compress JPEG files using `jpegoptim <http://www.kokkonen.net/tjko/projects.html>`_ -typogrify - Improve typography using `typogrify <https://github.com/mintchaos/typogrify>`_ + +You can apply filters to specific posts or pages by using the ``filters`` metadata field:: + + .. filters:: filters.html_tidy_nowrap, "sed s/foo/bar" + Optimizing Your Website @@ -1261,7 +1517,7 @@ different ones, or about other web servers, please share! AddType text/css .css -#. Optionally you can greate static compressed copies and save some CPU on your server +#. Optionally you can create static compressed copies and save some CPU on your server with the GZIP_FILES option in Nikola. #. The webassets Nikola plugin can drastically decrease the number of CSS and JS files your site fetches. @@ -1272,42 +1528,84 @@ different ones, or about other web servers, please share! #. The USE_CDN option offloads standard JavaScript and CSS files to a CDN so they are not downloaded from your server. -reStructuredText Extensions ---------------------------- - -Nikola includes support for a few directives and roles that are not part of docutils, but which -we think are handy for website development. +Math +---- + +Nikola supports math input via MathJax. It is activated via the math roles and +directives of reStructuredText and the usual LaTeX delimiters (``\(inline\)`` +and ``\[display\]``) for other input formats. + +We **DO NOT** support the old, deprecated and error-prone ``$inline$`` +delimiters by default. If you want to use them, please add them manually, +like this: + +.. code:: python + + """ + MATHJAX_CONFIG = """ + <script type="text/x-mathjax-config"> + MathJax.Hub.Config({ + tex2jax: { + inlineMath: [ ['$','$'], ["\\\(","\\\)"] ], + displayMath: [ ['$$','$$'], ["\\\[","\\\]"] ], + processEscapes: true + }, + displayAlign: 'left', // Change this to 'center' to center equations. + "HTML-CSS": { + styles: {'.MathJax_Display': {"margin": 0}} + } + }); + </script> + """ -MathJax -~~~~~~~ +Inline mathematics are produced using the reST `math` **role** or the ``\(…\)`` delimiters: -Nikola supports math input via MathJax. It uses the usual math roles and -directives of reStructuredText. +Euler’s formula: :math:`e^{ix} = \cos x + i\sin x` -In order to use them in your posts, you **must** add the special ``mathjax`` tag. +In reST: -Inline mathematics (equivalent to single dollar signs or backslash-parentheses -in LaTeX) are produced using the `math` **role**: +.. code:: restructuredtext -Euler’s formula: :math:`e^{ix} = \cos x + i\sin x` + Euler’s formula: :math:`e^{ix} = \cos x + i\sin x` -:: +In other input formats:: - Euler’s formula: :math:`e^{ix} = \cos x + i\sin x` + Euler’s formula: \(e^{ix} = \cos x + i\sin x\) -Display mathematics (equivalent to double dollar signs or backslash-brackets in -LaTeX) are produced using the `math` **directive**: +Display mathematics are produced using the reST `math` **directive** or the ``\[…\]`` delimiters: .. math:: \int \frac{dx}{1+ax}=\frac{1}{a}\ln(1+ax)+C + +In reST: + :: .. math:: \int \frac{dx}{1+ax}=\frac{1}{a}\ln(1+ax)+C +In other input formats: + +:: + + \[\int \frac{dx}{1+ax}=\frac{1}{a}\ln(1+ax)+C\] + +reStructuredText Extensions +--------------------------- + +Nikola includes support for a few directives and roles that are not part of docutils, but which +we think are handy for website development. + +Includes +~~~~~~~~ + +Nikola supports the standard reStructuredText ``include`` directive, but with a +catch: filenames are relative to **Nikola site root** (directory with ``conf.py``) +instead of the post location (eg. ``posts/`` directory)! + Media ~~~~~ @@ -1316,7 +1614,7 @@ URL of the page. For example here are two random videos:: .. media:: http://vimeo.com/72425090 - .. youtube:: http://www.youtube.com/watch?v=wyRpAat5oz0 + .. media:: http://www.youtube.com/watch?v=wyRpAat5oz0 It supports Instagram, Flickr, Github gists, Funny or Die, and dozens more, thanks to `Micawber <https://github.com/coleifer/micawber>`_ @@ -1381,18 +1679,28 @@ for ``code`` directive are provided: ``code-block`` and ``sourcecode``:: Listing ~~~~~~~ -To use this, you have to put your source code files inside ``listings`` or whatever your -``LISTINGS_FOLDER`` variable is set to. Assuming you have a ``foo.py`` inside that folder:: +To use this, you have to put your source code files inside ``listings`` or whatever folders +your ``LISTINGS_FOLDERS`` variable is set to fetch files from. Assuming you have a ``foo.py`` +inside one of these folders:: .. listing:: foo.py python Will include the source code from ``foo.py``, highlight its syntax in python mode, -and also create a ``listings/foo.py.html`` page and the listing will have a title linking to it. +and also create a ``listings/foo.py.html`` page (or in another directory, depending on +``LISTINGS_FOLDER``) and the listing will have a title linking to it. Listings support the same options `reST includes`__ support (including various options for controlling which parts of the file are included), and also a ``linenos`` option for Sphinx compatibility. +The ``LISTINGS_FOLDER`` configuration variable allows to specify a list of folders where +to fetch listings from together with subfolder of the ``output`` folder where the +processed listings should be put in. The default is, ``LISTINGS_FOLDERS = {'listings': 'listings'}``, +which means that all source code files in ``listings`` will be taken and stored in ``output/listings``. +Extending ``LISTINGS_FOLDERS`` to ``{'listings': 'listings', 'code': 'formatted-code'}`` +will additionally process all source code files in ``code`` and put the results into +``output/formatted-code``. + __ http://docutils.sourceforge.net/docs/ref/rst/directives.html#including-an-external-document-fragment .. note:: @@ -1415,6 +1723,29 @@ Producing this: This degrades gracefully if the browser doesn't support JavaScript. +Thumbnails +~~~~~~~~~~ + +To include an image placed in the ``images`` folder (or other folders defined in ``IMAGE_FOLDERS``), use the +``thumbnail`` directive, like this:: + + .. thumbnail:: ../tesla.jpg + +(make sure to check the file paths!) + +The small thumbnail will be placed in the page, and it will be linked to the bigger +version of the image when clicked, using +`colorbox <http://www.jacklmoore.com/colorbox>`_ by default. All options supported by +the reST `image <http://docutils.sourceforge.net/docs/ref/rst/directives.html#image>`_ +directive are supported (except ``target``). If a body element is provided, the +thumbnail will mimic the behavior of the +`figure <http://docutils.sourceforge.net/docs/ref/rst/directives.html#figure>`_ +directive instead:: + + .. thumbnail:: ../tesla.jpg + + Nikola Tesla, the man that invented the 20th century. + Slideshows ~~~~~~~~~~ @@ -1479,6 +1810,16 @@ and it will produce: Post List ~~~~~~~~~ +.. WARNING:: + + Any post or page that uses this directive will be considered out of date, + every time a post is added or deleted, causing maybe unnecessary rebuilds. + + On the other hand, it will sometimes **not** be considered out of date if + a post content changes, so it can sometimes be shown outdated, in those + cases, use ``nikola build -a`` to force a total rebuild. + + This directive can be used to generate a list of posts. You could use it, for example, to make a list of the latest 5 blog posts, or a list of all blog posts with the tag ``nikola``:: @@ -1486,26 +1827,70 @@ with the tag ``nikola``:: Here are my 5 latest and greatest blog posts: .. post-list:: - :start: -5 + :stop: 5 These are all my posts about Nikola: .. post-list:: :tags: nikola -Note that you can give the ``tags`` option a comma-separated list of tags, in -which case the list will show all posts that have at least one of those tags. -Other interesting options include ``stop`` (set it to ``-1``, for example, to -show all but the last post); ``reverse`` (set to ``True`` to sort the list in -chronological order, instead of the default latest-post-first); ``lang`` -(language to use for post titles and links); and ``slugs`` (allows you to filter -by post slugs, instead of tags). +The following options are recognized: + +* ``start`` : integer + The index of the first post to show. + A negative value like ``-3`` will show the *last* three posts in the + post-list. + Defaults to None. + +* ``stop`` : integer + The index of the last post to show. + A value negative value like ``-1`` will show every post, but not the + *last* in the post-list. + Defaults to None. + +* ``reverse`` : flag + Reverse the order of the post-list. + Defaults is to not reverse the order of posts. + +* ``sort``: string + Sort post list by one of each post's attributes, usually ``title`` or a + custom ``priority``. Defaults to None (chronological sorting). + +* ``tags`` : string [, string...] + Filter posts to show only posts having at least one of the ``tags``. + + Defaults to None. + +* ``slugs`` : string [, string...] + Filter posts to show only posts having at least one of the ``slugs``. + Defaults to None. + +* ``all`` : flag + Shows all posts and pages in the post list. + Defaults to show only posts with set *use_in_feeds*. + +* ``lang`` : string + The language of post *titles* and *links*. + Defaults to default language. + +* ``template`` : string + The name of an alternative template to render the post-list. + Defaults to ``post_list_directive.tmpl`` + +* ``id`` : string + A manual id for the post list. + Defaults to a random name composed by ``'post_list_' + uuid.uuid4().hex``. The post list directive uses the ``post_list_directive.tmpl`` template file (or another one, if you use the ``template`` option) to generate the list's HTML. By default, this is an unordered list with dates and clickable post titles. See the template file in Nikola's base theme for an example of how this works. +The list may fail to update in some cases, please run ``nikola build -a`` with +the appropriate path if this happens. + +We recommend using stories with dates in the past (1970-01-01) to avoid +dependency issues. Importing Your WordPress Site Into Nikola ----------------------------------------- @@ -1562,6 +1947,8 @@ Instead a new file with a timestamp at the end of the filename will be created. Using Twitter Cards ------------------- +Nikola supports Twitter Card summaries, but they are disabled by default. + Twitter Cards enable you to show additional information in Tweets that link to you content. Nikola supports `Twitter Cards <https://dev.twitter.com/docs/cards>`_. @@ -1570,24 +1957,25 @@ They are implemented to use *Open Graph* tags whenever possible. .. admonition:: Important To use Twitter Cards you need to opt-in on Twitter. - To do so please use the form that can be found at https://dev.twitter.com/form/participate-twitter-cards + To do so, please visit https://cards-dev.twitter.com/validator + +Images displayed come from the `previewimage` meta tag. -To enable and configure your use of Twitter Cards please modify the -corresponding lines in your ``conf.py``. -An example configuration that uses the Twitter nickname of the website -and the authors Twitter user ID is found below. +You can specify the card type by using the `card` parameter in TWITTER_CARD. + +To enable and configure your use of Twitter Cards, please modify the +corresponding lines in your ``conf.py``: .. code-block:: python TWITTER_CARD = { - 'use_twitter_cards': True, # enable Twitter Cards / Open Graph - 'site': '@website', # twitter nick for the website - # 'site:id': 123456, # Same as site, but the website's Twitter user ID instead. - # 'creator': '@username', # Username for the content creator / author. - 'creator:id': 654321, # Same as creator, but the Twitter user's ID. + 'use_twitter_cards': True, # enable Twitter Cards + 'card': 'summary', # Card type, you can also use 'summary_large_image', + # see https://dev.twitter.com/cards/types + 'site': '@website', # twitter nick for the website + 'creator': '@username', # Username for the content creator / author. } - Custom Plugins -------------- @@ -1599,7 +1987,7 @@ directories listed in the ``EXTRA_PLUGINS_DIRS`` configuration variable. Getting Extra Plugins --------------------- -If you want extra plugins, there is also the `Plugins Index <http://plugins.getnikola.com/>`_. +If you want extra plugins, there is also the `Plugins Index <https://plugins.getnikola.com/>`_. Similarly to themes, there is a nice, built-in command to manage them — ``plugin``:: @@ -1613,7 +2001,7 @@ Similarly to themes, there is a nice, built-in command to manage them — ⋮ $ nikola plugin --install helloworld - [2013-10-12T16:51:56Z] NOTICE: install_plugin: Downloading: http://plugins.getnikola.com/v6/helloworld.zip + [2013-10-12T16:51:56Z] NOTICE: install_plugin: Downloading: https://plugins.getnikola.com/v6/helloworld.zip [2013-10-12T16:51:58Z] NOTICE: install_plugin: Extracting: helloworld into plugins plugins/helloworld/requirements.txt [2013-10-12T16:51:58Z] NOTICE: install_plugin: This plugin has Python dependencies. @@ -1641,7 +2029,7 @@ And upgrade them:: [2014-04-15T09:00:18Z] WARNING: plugin: This is not very smart, it just reinstalls some plugins and hopes for the best Will upgrade 1 plugins: graphviz Upgrading graphviz - [2014-04-15T09:00:20Z] INFO: plugin: Downloading: http://plugins.getnikola.com/v7/graphviz.zip + [2014-04-15T09:00:20Z] INFO: plugin: Downloading: https://plugins.getnikola.com/v7/graphviz.zip [2014-04-15T09:00:20Z] INFO: plugin: Extracting: graphviz into /home/ralsina/.nikola/plugins/ [2014-04-15T09:00:20Z] NOTICE: plugin: This plugin has third-party dependencies you need to install manually. Contents of the requirements-nonpy.txt file: @@ -1658,8 +2046,19 @@ You can use the plugins in this repository without installing them into your site, by cloning the repository and adding the path of the plugins directory to the ``EXTRA_PLUGINS_DIRS`` list in your configuration. +Advanced Features +----------------- + +Debugging +~~~~~~~~~ + +For pdb debugging in Nikola, you should use ``doit.tools.set_trace()`` instead +of the usual pdb call. By default, doit (and thus Nikola) redirects stdout and +stderr. Thus, you must use the different call. (Alternatively, you could run +with ``nikola build -v 2``, which disables the redirections.) + Shell Tab Completion --------------------- +~~~~~~~~~~~~~~~~~~~~ Since Nikola is a command line tool, and this is the 21st century, it's handy to have smart tab-completion so that you don't have to type the full commands. diff --git a/docs/social_buttons.txt b/docs/social_buttons.txt index 0f039aa..9436ee7 100644 --- a/docs/social_buttons.txt +++ b/docs/social_buttons.txt @@ -8,7 +8,7 @@ Using Alternative Social Buttons with Nikola ============================================ -:Version: 7.1.0 +:Version: 7.6.0 .. class:: alert alert-info pull-right diff --git a/docs/sphinx/conf.py b/docs/sphinx/conf.py index 359cf1c..36cf31b 100644 --- a/docs/sphinx/conf.py +++ b/docs/sphinx/conf.py @@ -47,16 +47,16 @@ master_doc = 'index' # General information about the project. project = 'Nikola' -copyright = '2012-2014, The Nikola Contributors' +copyright = '2012-2015, The Nikola Contributors' # The version info for the project yo're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = '7.1.0' +version = '7.6.0' # The full version, including alpha/beta/rc tags. -release = '7.1.0' +release = '7.6.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/sphinx/index.txt b/docs/sphinx/index.txt index 1275b6c..c677caf 100644 --- a/docs/sphinx/index.txt +++ b/docs/sphinx/index.txt @@ -3,13 +3,12 @@ Nikola Documentation Those are the docs for the current GitHub master. It might be incompatible with the stable release. The docs for the stable release are available `on -the Nikola website <http://getnikola.com/documentation.html>`_. +the Nikola website <https://getnikola.com/documentation.html>`_. .. toctree:: :maxdepth: 5 manual - upgrading-to-v6 creating-a-site creating-a-theme theming diff --git a/docs/sphinx/upgrading-to-v6.txt b/docs/sphinx/upgrading-to-v6.txt deleted file mode 120000 index 1c7e16f..0000000 --- a/docs/sphinx/upgrading-to-v6.txt +++ /dev/null @@ -1 +0,0 @@ -../upgrading-to-v6.txt
\ No newline at end of file diff --git a/docs/getting-help.txt b/docs/support.rst index 567ab66..0d4fc3a 100644 --- a/docs/getting-help.txt +++ b/docs/support.rst @@ -1,9 +1,9 @@ -.. title: Help, Bugs, Contact +.. title: Support and Contact .. slug: contact .. date: 1970-01-01 15:00:00 .. description: Get help using Nikola, or contact us. -:Version: 7.1.0 +:Version: 7.5.1 .. class:: alert alert-info pull-right diff --git a/docs/theming.txt b/docs/theming.txt index 2e2a516..f9667ed 100644 --- a/docs/theming.txt +++ b/docs/theming.txt @@ -8,7 +8,7 @@ Theming Nikola ============== -:Version: 7.1.0 +:Version: 7.6.0 :Author: Roberto Alsina <ralsina@netmanagers.com.ar> .. class:: alert alert-info pull-right @@ -68,10 +68,9 @@ parent I recommend this: - * If your theme uses bootstrap, inherit the ``bootstrap`` theme. - * If your theme uses bootstrap3, inherit the ``bootstrap3`` theme. + * If your theme uses Bootstrap 3, inherit the ``bootstrap3`` theme. * If your theme uses Jinja as a template engine, inherit ``base-jinja`` - or ``bootstrap-jinja`` (available at http://themes.nikola.ralsina.com.ar) + or ``bootstrap3-jinja`` * In any other case, inherit ``base``. And these optional files: @@ -84,7 +83,7 @@ bundles A text file containing a list of files to be turned into bundles using WebAssets. For example:: - assets/css/all.css=bootstrap.css,bootstrap-responsive.css,rst.css,code.css,colorbox.css,custom.css + assets/css/all.css=bootstrap.css,rst.css,code.css,colorbox.css,custom.css This creates a file called "assets/css/all.css" in your output that is the combination of all the other file paths, relative to the output file. @@ -117,29 +116,31 @@ These are the templates that come with the included themes: This template defines the basic page layout for the site. It's mostly plain HTML but defines a few blocks that can be re-defined by inheriting templates. - It has some separate pieces defined in ``base_helper.tmpl`` so they can be - easily overriden. For example, the Bootstrap theme adds a ``bootstrap_helper.tmpl`` - and then uses it to override things defined in base theme's ``base_helper.tmpl`` + It has some separate pieces defined in ``base_helper.tmpl``, + ``base_header.tmpl`` and ``base_footer.tmpl`` so they can be + easily overriden. ``index.tmpl`` Template used to render the multipost indexes. The posts are in a ``posts`` variable. Some functionality is in the ``index_helper.tmpl`` helper template. +``archiveindex.tmpl`` + Used to display archives, if ``ARCHIVES_ARE_INDEXES`` is True. + By default, it just inherits ``index.tmpl``. + ``comments_helper.tmpl`` This template handles comments. You should probably never touch it :-) - It uses a bunch of helper templates, one for each supported comment system: - ``disqus_helper.tmpl`` ``facebook_helper.tmpl`` ``googleplus_helper.tmpl`` - ``intensedebate_helper.tmpl`` ``isso_helper.tmpl`` ``livefyre_helper.tmpl`` - ``moot_helper.tmpl`` + It uses a bunch of helper templates, one for each supported comment system + (all of which start with ``comments_helper``) -``crumbs.tmpl`` ``slides.tmpl`` +``crumbs.tmpl``, ``slides.tmpl`` These templates help render specific UI items, and can be tweaked as needed. ``gallery.tmpl`` Template used for image galleries. Interesting data includes: - * ``text``: A descriptive text for the gallery. - * ``crumbs``: A list of ``link, crumb`` to implement a crumbbar. + * ``post``: A post object, containing descriptive ``post.text()`` for the gallery. + * ``crumbs``: A list of ``link, crumb`` to implement breadcrumbs. * ``folders``: A list of folders to implement hierarchical gallery navigation. * ``enable_comments``: To enable/disable comments in galleries. * ``thumbnail_size``: The ``THUMBNAIL_SIZE`` option. @@ -159,26 +160,31 @@ These are the templates that come with the included themes: ``list_post.tmpl`` Template used to display generic lists of posts, which it gets in ``posts``. +``listing.tmpl`` + Used to display code listings. + ``post.tmpl`` Template used by default for blog posts, gets the data in a ``post`` object which is an instance of the Post class. Some functionality is in the - ``post_helper.tmpl`` template. + ``post_helper.tmpl`` and ``post_header.tmpl`` templates. + +``post_list_directive.tmpl`` + Template used by the ``post_list`` reStructuredText directive. ``story.tmpl`` Used for pages that are not part of a blog, usually a cleaner, less intrusive layout than ``post.tmpl``, but same parameters. -``listing.tmpl`` - Used to display code listings. - -``tags.tmpl`` - Used to display the list of tags and categories. ``tag.tmpl`` is used to show the contents - of a single tag or category. +``tag.tmpl`` + Used to show the contents of a single tag or category. ``tagindex.tmpl`` - Used to display tag indexes, if ``TAG_PAGES_ARE_INDEXES`` is True. + Used to show the contents of a single tag or category, if ``TAG_PAGES_ARE_INDEXES`` is True. By default, it just inherits ``index.tmpl``. +``tags.tmpl`` + Used to display the list of tags and categories. + You can add other templates for specific pages, which the user can then use in his ``POSTS`` or ``PAGES`` option in ``conf.py``. Also, keep in mind that your theme is yours, there is no reason why you would need to maintain the inheritance as it is, or not diff --git a/docs/upgrading-to-v6.txt b/docs/upgrading-to-v6.txt deleted file mode 100644 index 271d98e..0000000 --- a/docs/upgrading-to-v6.txt +++ /dev/null @@ -1,111 +0,0 @@ -.. title: Upgrading to v6 -.. slug: upgrading-to-v6 -.. date: 2013-08-23 23:00:00 UTC-03:00 -.. tags: -.. link: -.. description: - -Upgrading to v6 -=============== - -:Version: 7.1.0 - -.. class:: lead - -Nikola tries fairly hard to be compatible between versions. However, there were -a few areas which were getting clunky, and needed fxing. So, here's what you may -need to change in your site. - -If you need to change anything else, or something breaks, please write at nikola-discuss -and I'll add further tweaks here. - -Themes ------- - -**NOTE** - There is no equivalent for the jinja-default theme yet. If you have a custom, - jinja-based theme, upgrading is probably a bad idea right now. - - -Themes have been renamed: - -* site => bootstrap -* orphan => base - -Theme added: - -* base-jinja - -Themes have been moved out of nikola and into nikola-themes: - -* default => oldfashioned at nikola-themes -* jinja-default => not there yet, coming soon -* monospace => monospace at nikola-themes -* site-reveal => reveal at nikola-themes - -You may have to change your ``THEME`` setting, or change the ``parent`` if you are -using a custom theme. Also, some templates have been tweaked, but nothing should -break for you. - -Facebook comments support changed the HTML tag to: - -.. code-block:: mako - - <html - %if comment_system == 'facebook': - xmlns:fb="http://ogp.me/ns/fb#" - %endif - lang="${lang}"> - -If you do not want to use Facebook comments, you can leave the old ``<html -lang="${lang}">`` tag in and it will work just fine. - -Comments -~~~~~~~~ - -If you want a custom theme to support comment systems other than disqus, you will need to: - -1) Replace mentions of disqus_helper.tmpl with comments_helper.tmpl -2) Replace mentions of html_disqus with comment_form -3) Replace mentions of html_disqus_link with comment_link -4) Replace mentions of html_disqus_script with comment_link_script - -If you don't, your theme should work just fine, but support only disqus comments. - - -Configuration -------------- - -A number of options have been renamed. In most cases, the behaviour -should be **exactly** as before. - -However, ``post_pages`` was split into ``POSTS`` and ``PAGES``. Long -story short, anything that had a ``True`` as the ``use_in_feeds`` -(last) value goes to ``POSTS`` and anything with ``False`` goes to -``PAGES``. For example: - -.. code-block:: python - - post_pages = ( - ("posts/*.txt", "", "post.tmpl", True), - ("stories/*.txt", "p", "story.tmpl", False), - ("stories/*.html", "s", "story.tmpl", False), - ) - - ### becomes ### - - POSTS = ( - ("posts/*.txt", "", "post.tmpl"), - ) - - PAGES = ( - ("stories/*.txt", "p", "story.tmpl"), - ("stories/*.html", "s", "story.tmpl"), - ) - -Also, you will get warnings. That doesn't mean things broke. They are -there to inform you of what's happening, and that you need to tweak your -config. - -All the deprecated options will work during the v6 cycle, and only be -removed in v7, when those warnings will become errors. @@ -30,6 +30,7 @@ def task_locale(): def set_nikola_test_locales(): try: out = subprocess.check_output(['locale', '-a']) + out = out.decode('utf-8') locales = [] languages = set() for line in out.splitlines(): @@ -37,7 +38,7 @@ def task_locale(): lang = line.split('_')[0] if lang not in languages: try: - locale.setlocale(locale.LC_ALL, line) + locale.setlocale(locale.LC_ALL, str(line)) except: continue languages.add(lang) diff --git a/nikola/__init__.py b/nikola/__init__.py index 4cb5427..263874f 100644 --- a/nikola/__init__.py +++ b/nikola/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -27,7 +27,7 @@ from __future__ import absolute_import import os -__version__ = "7.1.0" +__version__ = "7.6.0" DEBUG = bool(os.getenv('NIKOLA_DEBUG')) from .nikola import Nikola # NOQA diff --git a/nikola/__main__.py b/nikola/__main__.py index f492800..6aa0977 100644 --- a/nikola/__main__.py +++ b/nikola/__main__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -25,7 +25,7 @@ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import print_function, unicode_literals -from operator import attrgetter +from collections import defaultdict import os import shutil try: @@ -49,10 +49,18 @@ from blinker import signal from . import __version__ from .plugin_categories import Command from .nikola import Nikola -from .utils import _reload, sys_decode, get_root_dir, req_missing, LOGGER, STRICT_HANDLER, ColorfulStderrHandler +from .utils import sys_decode, sys_encode, get_root_dir, req_missing, LOGGER, STRICT_HANDLER, ColorfulStderrHandler + +if sys.version_info[0] == 3: + import importlib.machinery +else: + import imp config = {} +# DO NOT USE unless you know what you are doing! +_RETURN_DOITNIKOLA = False + def main(args=None): colorful = False @@ -63,16 +71,34 @@ def main(args=None): if args is None: args = sys.argv[1:] + + oargs = args + args = [sys_decode(arg) for arg in args] + + conf_filename = 'conf.py' + conf_filename_bytes = b'conf.py' + conf_filename_changed = False + for index, arg in enumerate(args): + if arg[:7] == '--conf=': + del args[index] + del oargs[index] + conf_filename = arg[7:] + conf_filename_bytes = sys_encode(arg[7:]) + conf_filename_changed = True + break + quiet = False - if len(args) > 0 and args[0] == b'build' and b'--strict' in args: + if len(args) > 0 and args[0] == 'build' and '--strict' in args: LOGGER.notice('Running in strict mode') STRICT_HANDLER.push_application() - if len(args) > 0 and args[0] == b'build' and b'-q' in args or b'--quiet' in args: + if len(args) > 0 and args[0] == 'build' and '-q' in args or '--quiet' in args: nullhandler = NullHandler() nullhandler.push_application() quiet = True global config + original_cwd = os.getcwd() + # Those commands do not require a `conf.py`. (Issue #1132) # Moreover, actually having one somewhere in the tree can be bad, putting # the output of that command (the new site) in an unknown directory that is @@ -82,25 +108,38 @@ def main(args=None): root = get_root_dir() if root: os.chdir(root) + # Help and imports don't require config, but can use one if it exists + needs_config_file = (argname != 'help') and not argname.startswith('import_') + else: + needs_config_file = False sys.path.append('') try: - import conf - _reload(conf) + if sys.version_info[0] == 3: + loader = importlib.machinery.SourceFileLoader("conf", conf_filename) + conf = loader.load_module() + else: + conf = imp.load_source("conf", conf_filename_bytes) config = conf.__dict__ except Exception: - if os.path.exists('conf.py'): + if os.path.exists(conf_filename): msg = traceback.format_exc(0) - LOGGER.error('conf.py cannot be parsed.\n{0}'.format(msg)) - sys.exit(1) + LOGGER.error('"{0}" cannot be parsed.\n{1}'.format(conf_filename, msg)) + return 1 + elif needs_config_file and conf_filename_changed: + LOGGER.error('Cannot find configuration file "{0}".'.format(conf_filename)) + return 1 config = {} + if conf_filename_changed: + LOGGER.info("Using config file '{0}'".format(conf_filename)) + invariant = False - if len(args) > 0 and args[0] == b'build' and b'--invariant' in args: + if len(args) > 0 and args[0] == 'build' and '--invariant' in args: try: import freezegun - freeze = freezegun.freeze_time("2014-01-01") + freeze = freezegun.freeze_time("2038-01-01") freeze.start() invariant = True except ImportError: @@ -114,9 +153,13 @@ def main(args=None): config['__colorful__'] = colorful config['__invariant__'] = invariant config['__quiet__'] = quiet - + config['__configuration_filename__'] = conf_filename + config['__cwd__'] = original_cwd site = Nikola(**config) - _ = DoitNikola(site, quiet).run(args) + DN = DoitNikola(site, quiet) + if _RETURN_DOITNIKOLA: + return DN + _ = DN.run(oargs) if site.invariant: freeze.stop() @@ -135,10 +178,11 @@ class Help(DoitHelp): # --strict, --invariant and --quiet. del cmds['run'] - print("Nikola is a tool to create static websites and blogs. For full documentation and more information, please visit http://getnikola.com/\n\n") + print("Nikola is a tool to create static websites and blogs. For full documentation and more information, please visit https://getnikola.com/\n\n") print("Available commands:") - for cmd in sorted(cmds.values(), key=attrgetter('name')): - print(" nikola %-*s %s" % (20, cmd.name, cmd.doc_purpose)) + for cmd_name in sorted(cmds.keys()): + cmd = cmds[cmd_name] + print(" nikola {:20s} {}".format(cmd_name, cmd.doc_purpose)) print("") print(" nikola help show help / reference") print(" nikola help <command> show command usage") @@ -214,12 +258,13 @@ class NikolaTaskLoader(TaskLoader): 'outfile': sys.stderr, } DOIT_CONFIG['default_tasks'] = ['render_site', 'post_render'] + DOIT_CONFIG.update(self.nikola._doit_config) tasks = generate_tasks( 'render_site', self.nikola.gen_tasks('render_site', "Task", 'Group of tasks to render the site.')) latetasks = generate_tasks( 'post_render', - self.nikola.gen_tasks('post_render', "LateTask", 'Group of tasks to be executes after site is rendered.')) + self.nikola.gen_tasks('post_render', "LateTask", 'Group of tasks to be executed after site is rendered.')) signal('initialized').send(self.nikola) return tasks + latetasks, DOIT_CONFIG @@ -230,20 +275,21 @@ class DoitNikola(DoitMain): TASK_LOADER = NikolaTaskLoader def __init__(self, nikola, quiet=False): + super(DoitNikola, self).__init__() self.nikola = nikola nikola.doit = self self.task_loader = self.TASK_LOADER(nikola, quiet) - def get_commands(self): + def get_cmds(self): # core doit commands - cmds = DoitMain.get_commands(self) + cmds = DoitMain.get_cmds(self) # load nikola commands for name, cmd in self.nikola._commands.items(): cmds[name] = cmd return cmds def run(self, cmd_args): - sub_cmds = self.get_commands() + sub_cmds = self.get_cmds() args = self.process_args(cmd_args) args = [sys_decode(arg) for arg in args] @@ -270,18 +316,30 @@ class DoitNikola(DoitMain): args = ['version'] if args[0] not in sub_cmds.keys(): LOGGER.error("Unknown command {0}".format(args[0])) - return False - if not isinstance(sub_cmds[args[0]], (Command, Help)): # Is a doit command + sugg = defaultdict(list) + for c in sub_cmds.keys(): + d = lev(c, args[0]) + sugg[d].append(c) + LOGGER.info('Did you mean "{}"?', '" or "'.join(sugg[min(sugg.keys())])) + return 3 + if sub_cmds[args[0]] is not Help and not isinstance(sub_cmds[args[0]], Command): # Is a doit command if not self.nikola.configured: LOGGER.error("This command needs to run inside an " "existing Nikola site.") - return False - + return 3 return super(DoitNikola, self).run(cmd_args) @staticmethod def print_version(): print("Nikola v" + __version__) + +# Stolen from http://stackoverflow.com/questions/4173579/implementing-levenshtein-distance-in-python +def lev(a, b): + if not a or not b: + return max(len(a), len(b)) + return min(lev(a[1:], b[1:]) + (a[0] != b[0]), lev(a[1:], b) + 1, lev(a, b[1:]) + 1) + + if __name__ == "__main__": sys.exit(main(sys.argv[1:])) diff --git a/nikola/conf.py.in b/nikola/conf.py.in index 04c2098..ab00673 100644 --- a/nikola/conf.py.in +++ b/nikola/conf.py.in @@ -23,7 +23,7 @@ BLOG_TITLE = ${BLOG_TITLE} # (translatable) # This is the main URL for your site. It will be used # in a prominent link SITE_URL = ${SITE_URL} -# This is the URL where nikola's output will be deployed. +# This is the URL where Nikola's output will be deployed. # If not set, defaults to SITE_URL # BASE_URL = ${SITE_URL} BLOG_EMAIL = ${BLOG_EMAIL} @@ -63,19 +63,26 @@ TRANSLATIONS_PATTERN = ${TRANSLATIONS_PATTERN} # This is a dict. The keys are languages, and values are tuples. # # For regular links: -# ('http://example.com/', 'Text') +# ('https://getnikola.com/', 'Nikola Homepage') # # For submenus: -# (( -# ('Sub 1', 'http://example.com/'), -# ('Sub 2', 'http://example.org/'), -# ), 'Top') +# ( +# ( +# ('http://apple.com/', 'Apple'), +# ('http://orange.com/', 'Orange'), +# ), +# 'Fruits' +# ) # # WARNING: Support for submenus is theme-dependent. # Only one level of submenus is supported. # WARNING: Some themes, including the default Bootstrap 3 theme, # may present issues if the menu is too large. # (in bootstrap3, the navbar can grow too large and cover contents.) +# WARNING: If you link to directories, make sure to follow +# ``STRIP_INDEXES``. If it’s set to ``True``, end your links +# with a ``/``, otherwise end them with ``/index.html`` — or +# else they won’t be highlighted when active. NAVIGATION_LINKS = ${NAVIGATION_LINKS} @@ -90,7 +97,7 @@ THEME = ${THEME} # another time zone, please set TIMEZONE to match. Check the available # list from Wikipedia: # http://en.wikipedia.org/wiki/List_of_tz_database_time_zones -# (eg. 'Europe/Zurich') +# (e.g. 'Europe/Zurich') # Also, if you want to use a different time zone in some of your posts, # you can use the ISO 8601/RFC 3339 format (ex. 2012-03-30T23:00:00+02:00) TIMEZONE = ${TIMEZONE} @@ -104,13 +111,26 @@ TIMEZONE = ${TIMEZONE} # (str used by datetime.datetime.strftime) # DATE_FORMAT = '%Y-%m-%d %H:%M' -# While nikola can select a sensible locale for each language, +# Date format used to display post dates, if local dates are used. +# (str used by moment.js) +# JS_DATE_FORMAT = 'YYYY-MM-DD HH:mm' + +# Date fanciness. +# +# 0 = using DATE_FORMAT and TIMEZONE +# 1 = using JS_DATE_FORMAT and local user time (via moment.js) +# 2 = using a string like “2 days ago” +# +# Your theme must support it, bootstrap and bootstrap3 already do. +# DATE_FANCINESS = 0 + +# While Nikola can select a sensible locale for each language, # sometimes explicit control can come handy. # In this file we express locales in the string form that # python's locales will accept in your OS, by example -# "en_US.utf8" in unix-like OS, "English_United States" in Windows. +# "en_US.utf8" in Unix-like OS, "English_United States" in Windows. # LOCALES = dict mapping language --> explicit locale for the languages -# in TRANSLATIONS. You can ommit one or more keys. +# in TRANSLATIONS. You can omit one or more keys. # LOCALE_FALLBACK = locale to use when an explicit locale is unavailable # LOCALE_DEFAULT = locale to use for languages not mentioned in LOCALES; if # not set the default Nikola mapping is used. @@ -121,7 +141,7 @@ TIMEZONE = ${TIMEZONE} # (whatever/thing.txt). # # That fragment could have an associated metadata file (whatever/thing.meta), -# and optionally translated files (example for spanish, with code "es"): +# and optionally translated files (example for Spanish, with code "es"): # whatever/thing.es.txt and whatever/thing.es.meta # # This assumes you use the default TRANSLATIONS_PATTERN. @@ -129,7 +149,7 @@ TIMEZONE = ${TIMEZONE} # From those files, a set of HTML fragment files will be generated: # cache/whatever/thing.html (and maybe cache/whatever/thing.html.es) # -# These files are combinated with the template to produce rendered +# These files are combined with the template to produce rendered # pages, which will be placed at # output / TRANSLATIONS[lang] / destination / pagename.html # @@ -144,18 +164,24 @@ POSTS = ${POSTS} PAGES = ${PAGES} # One or more folders containing files to be copied as-is into the output. -# The format is a dictionary of "source" "relative destination". +# The format is a dictionary of {source: relative destination}. # Default is: -# FILES_FOLDERS = {'files': '' } +# FILES_FOLDERS = {'files': ''} # Which means copy 'files' into 'output' +# One or more folders containing listings to be processed and stored into +# the output. The format is a dictionary of {source: relative destination}. +# Default is: +# LISTINGS_FOLDERS = {'listings': 'listings'} +# Which means process listings from 'listings' into 'output/listings' + # A mapping of languages to file-extensions that represent that language. # Feel free to add or delete extensions to any list, but don't add any new # compilers unless you write the interface for it yourself. # # 'rest' is reStructuredText # 'markdown' is MarkDown -# 'html' assumes the file is html and just copies it +# 'html' assumes the file is HTML and just copies it COMPILERS = ${COMPILERS} # Create by default posts in one file format? @@ -178,6 +204,10 @@ COMPILERS = ${COMPILERS} # already contains the text), set this to False. # SHOW_BLOG_TITLE = True +# Writes tag cloud data in form of tag_cloud_data.json. +# Warning: this option will change its default value to False in v8! +WRITE_TAG_CLOUD = True + # Paths for different autogenerated bits. These are combined with the # translation paths. @@ -191,6 +221,64 @@ COMPILERS = ${COMPILERS} # the posts themselves. If set to False, it will be just a list of links. # TAG_PAGES_ARE_INDEXES = False +# Set descriptions for tag pages to make them more interesting. The +# default is no description. The value is used in the meta description +# and displayed underneath the tag list or index page’s title. +# TAG_PAGES_DESCRIPTIONS = { +# DEFAULT_LANG: { +# "blogging": "Meta-blog posts about blogging about blogging.", +# "open source": "My contributions to my many, varied, ever-changing, and eternal libre software projects." +# }, +#} + + +# If you do not want to display a tag publicly, you can mark it as hidden. +# The tag will not be displayed on the tag list page, the tag cloud and posts. +# Tag pages will still be generated. +HIDDEN_TAGS = ['mathjax'] + +# Only include tags on the tag list/overview page if there are at least +# TAGLIST_MINIMUM_POSTS number of posts or more with every tag. Every tag +# page is still generated, linked from posts, and included in the sitemap. +# However, more obscure tags can be hidden from the tag index page. +# TAGLIST_MINIMUM_POSTS = 1 + +# Final locations are: +# output / TRANSLATION[lang] / CATEGORY_PATH / index.html (list of categories) +# output / TRANSLATION[lang] / CATEGORY_PATH / CATEGORY_PREFIX category.html (list of posts for a category) +# output / TRANSLATION[lang] / CATEGORY_PATH / CATEGORY_PREFIX category.xml (RSS feed for a category) +# CATEGORY_PATH = "categories" +# CATEGORY_PREFIX = "cat_" + +# If CATEGORY_ALLOW_HIERARCHIES is set to True, categories can be organized in +# hierarchies. For a post, the whole path in the hierarchy must be specified, +# using a forward slash ('/') to separate paths. Use a backslash ('\') to escape +# a forward slash or a backslash (i.e. '\//\\' is a path specifying the +# subcategory called '\' of the top-level category called '/'). +# CATEGORY_ALLOW_HIERARCHIES = False +# If CATEGORY_OUTPUT_FLAT_HIERARCHY is set to True, the output written to output +# contains only the name of the leaf category and not the whole path. +# CATEGORY_OUTPUT_FLAT_HIERARCHY = False + +# If CATEGORY_PAGES_ARE_INDEXES is set to True, each category's page will contain +# the posts themselves. If set to False, it will be just a list of links. +# CATEGORY_PAGES_ARE_INDEXES = False + +# Set descriptions for category pages to make them more interesting. The +# default is no description. The value is used in the meta description +# and displayed underneath the category list or index page’s title. +# CATEGORY_PAGES_DESCRIPTIONS = { +# DEFAULT_LANG: { +# "blogging": "Meta-blog posts about blogging about blogging.", +# "open source": "My contributions to my many, varied, ever-changing, and eternal libre software projects." +# }, +#} + +# If you do not want to display a category publicly, you can mark it as hidden. +# The category will not be displayed on the category list page. +# Category pages will still be generated. +HIDDEN_CATEGORIES = [] + # Final location for the main blog page and sibling paginated pages is # output / TRANSLATION[lang] / INDEX_PATH / index-*.html # INDEX_PATH = "" @@ -199,13 +287,24 @@ COMPILERS = ${COMPILERS} # CREATE_MONTHLY_ARCHIVE = False # Create one large archive instead of per-year # CREATE_SINGLE_ARCHIVE = False +# Create year, month, and day archives each with a (long) list of posts +# (overrides both CREATE_MONTHLY_ARCHIVE and CREATE_SINGLE_ARCHIVE) +# CREATE_FULL_ARCHIVES = False +# If monthly archives or full archives are created, adds also one archive per day +# CREATE_DAILY_ARCHIVE = False # Final locations for the archives are: # output / TRANSLATION[lang] / ARCHIVE_PATH / ARCHIVE_FILENAME # output / TRANSLATION[lang] / ARCHIVE_PATH / YEAR / index.html # output / TRANSLATION[lang] / ARCHIVE_PATH / YEAR / MONTH / index.html +# output / TRANSLATION[lang] / ARCHIVE_PATH / YEAR / MONTH / DAY / index.html # ARCHIVE_PATH = "" # ARCHIVE_FILENAME = "archive.html" +# If ARCHIVES_ARE_INDEXES is set to True, each archive page which contains a list +# of posts will contain the posts themselves. If set to False, it will be just a +# list of links. +# ARCHIVES_ARE_INDEXES = False + # URLs to other posts/pages can take 3 forms: # rel_path: a relative URL to the current page/post (default) # full_path: a URL with the full path from the root @@ -232,15 +331,23 @@ COMPILERS = ${COMPILERS} # If you don't need any of these, just set to [] REDIRECTIONS = ${REDIRECTIONS} -# Commands to execute to deploy. Can be anything, for example, -# you may use rsync: +# Presets of commands to execute to deploy. Can be anything, for +# example, you may use rsync: # "rsync -rav --delete output/ joe@my.site:/srv/www/site" # And then do a backup, or run `nikola ping` from the `ping` -# plugin (`nikola install_plugin ping`). -# To do manual deployment, set it to [] -# DEPLOY_COMMANDS = [] +# plugin (`nikola plugin -i ping`). Or run `nikola check -l`. +# You may also want to use github_deploy (see below). +# You can define multiple presets and specify them as arguments +# to `nikola deploy`. If no arguments are specified, a preset +# named `default` will be executed. You can use as many presets +# in a `nikola deploy` command as you like. +# DEPLOY_COMMANDS = { +# 'default': [ +# "rsync -rav --delete output/ joe@my.site:/srv/www/site", +# ] +# } -# For user.github.io/organization.github.io pages, the DEPLOY branch +# For user.github.io OR organization.github.io pages, the DEPLOY branch # MUST be 'master', and 'gh-pages' for other repositories. # GITHUB_SOURCE_BRANCH = 'master' # GITHUB_DEPLOY_BRANCH = 'gh-pages' @@ -278,7 +385,7 @@ REDIRECTIONS = ${REDIRECTIONS} # Nikola’s templates. All other filters must be enabled through FILTERS. # # Many filters are shipped with Nikola. A list is available in the manual: -# <http://getnikola.com/handbook.html#post-processing-filters> +# <https://getnikola.com/handbook.html#post-processing-filters> # # from nikola import filters # FILTERS = { @@ -291,7 +398,7 @@ REDIRECTIONS = ${REDIRECTIONS} # side optimization for very high traffic sites or low memory servers. # GZIP_FILES = False # File extensions that will be compressed -# GZIP_EXTENSIONS = ('.txt', '.htm', '.html', '.css', '.js', '.json', '.xml') +# GZIP_EXTENSIONS = ('.txt', '.htm', '.html', '.css', '.js', '.json', '.atom', '.xml') # Use an external gzip command? None means no. # Example: GZIP_COMMAND = "pigz -k {filename}" # GZIP_COMMAND = None @@ -318,9 +425,13 @@ REDIRECTIONS = ${REDIRECTIONS} # Image Gallery Options # ############################################################################# -# Galleries are folders in galleries/ -# Final location of galleries will be output / GALLERY_PATH / gallery_name -# GALLERY_PATH = "galleries" +# One or more folders containing galleries. The format is a dictionary of +# {"source": "relative_destination"}, where galleries are looked for in +# "source/" and the results will be located in +# "OUTPUT_PATH/relative_destination/gallery_name" +# Default is: +# GALLERY_FOLDERS = {"galleries": "galleries"} +# More gallery options: # THUMBNAIL_SIZE = 180 # MAX_IMAGE_SIZE = 1280 # USE_FILENAME_AS_TITLE = True @@ -328,23 +439,94 @@ REDIRECTIONS = ${REDIRECTIONS} # # If set to False, it will sort by filename instead. Defaults to True # GALLERY_SORT_BY_DATE = True +# +# Folders containing images to be used in normal posts or pages. Images will be +# scaled down according to IMAGE_THUMBNAIL_SIZE and MAX_IMAGE_SIZE options, but +# will have to be referenced manually to be visible on the site +# (the thumbnail has ``.thumbnail`` added before the file extension). +# The format is a dictionary of {source: relative destination}. + +IMAGE_FOLDERS = {'images': 'images'} +# IMAGE_THUMBNAIL_SIZE = 400 # ############################################################################# # HTML fragments and diverse things that are used by the templates # ############################################################################# # Data about post-per-page indexes. -# INDEXES_PAGES defaults to 'old posts, page %d' or 'page %d' (translated), +# INDEXES_PAGES defaults to ' old posts, page %d' or ' page %d' (translated), # depending on the value of INDEXES_PAGES_MAIN. -# INDEXES_TITLE = "" # If this is empty, defaults to BLOG_TITLE -# INDEXES_PAGES = "" # If this is empty, defaults to '[old posts,] page %d' (see above) -# INDEXES_PAGES_MAIN = False # If True, INDEXES_PAGES is also displayed on -# # the main (the newest) index page (index.html) +# +# (translatable) If the following is empty, defaults to BLOG_TITLE: +# INDEXES_TITLE = "" +# +# (translatable) If the following is empty, defaults to ' [old posts,] page %d' (see above): +# INDEXES_PAGES = "" +# +# If the following is True, INDEXES_PAGES is also displayed on the main (the +# newest) index page (index.html): +# INDEXES_PAGES_MAIN = False +# +# If the following is True, index-1.html has the oldest posts, index-2.html the +# second-oldest posts, etc., and index.html has the newest posts. This ensures +# that all posts on index-x.html will forever stay on that page, now matter how +# many new posts are added. +# If False, index-1.html has the second-newest posts, index-2.html the third-newest, +# and index-n.html the oldest posts. When this is active, old posts can be moved +# to other index pages when new posts are added. +# INDEXES_STATIC = True +# +# (translatable) If PRETTY_URLS is set to True, this setting will be used to create +# prettier URLs for index pages, such as page/2/index.html instead of index-2.html. +# Valid values for this settings are: +# * False, +# * a list or tuple, specifying the path to be generated, +# * a dictionary mapping languages to lists or tuples. +# Every list or tuple must consist of strings which are used to combine the path; +# for example: +# ['page', '{number}', '{index_file}'] +# The replacements +# {number} --> (logical) page number; +# {old_number} --> the page number inserted into index-n.html before (zero for +# the main page); +# {index_file} --> value of option INDEX_FILE +# are made. +# Note that in case INDEXES_PAGES_MAIN is set to True, a redirection will be created +# for the full URL with the page number of the main page to the normal (shorter) main +# page URL. +# INDEXES_PRETTY_PAGE_URL = False # Color scheme to be used for code blocks. If your theme provides # "assets/css/code.css" this is ignored. -# Can be any of autumn borland bw colorful default emacs friendly fruity manni -# monokai murphy native pastie perldoc rrt tango trac vim vs +# Can be any of: +# algol +# algol_nu +# arduino +# autumn +# borland +# bw +# colorful +# default +# emacs +# friendly +# fruity +# igor +# lovelace +# manni +# monokai +# murphy +# native +# paraiso_dark +# paraiso_light +# pastie +# perldoc +# rrt +# tango +# trac +# vim +# vs +# xcode +# This list MAY be incomplete since pygments adds styles every now and then. # CODE_COLOR_SCHEME = 'default' # If you use 'site-reveal' theme you can select several subthemes @@ -357,12 +539,12 @@ REDIRECTIONS = ${REDIRECTIONS} # You can also use: page/concave/linear/none/default # FAVICONS contains (name, file, size) tuples. -# Used for create favicon link like this: +# Used to create favicon link like this: # <link rel="name" href="file" sizes="size"/> -# FAVICONS = { +# FAVICONS = ( # ("icon", "/favicon.ico", "16x16"), # ("icon", "/icon_128x128.png", "128x128"), -# } +# ) # Show only teasers in the index pages? Defaults to False. # INDEX_TEASERS = False @@ -384,6 +566,16 @@ INDEX_READ_MORE_LINK = ${INDEX_READ_MORE_LINK} # 'Read more...' for the RSS_FEED, if RSS_TEASERS is True (translatable) RSS_READ_MORE_LINK = ${RSS_READ_MORE_LINK} +# Append a URL query to the RSS_READ_MORE_LINK in Atom and RSS feeds. Advanced +# option used for traffic source tracking. +# Minimum example for use with Piwik: "pk_campaign=feed" +# The following tags exist and are replaced for you: +# {feedRelUri} A relative link to the feed. +# {feedFormat} The name of the syndication format. +# Example using replacement for use with Google Analytics: +# "utm_source={feedRelUri}&utm_medium=nikola_feed&utm_campaign={feedFormat}_feed" +RSS_LINKS_APPEND_QUERY = False + # A HTML fragment describing the license, for the sidebar. # (translatable) LICENSE = "" @@ -399,7 +591,7 @@ LICENSE = "" # (translatable) CONTENT_FOOTER = 'Contents © {date} \ <a href="mailto:{email}">{author}</a> - Powered by \ - <a href="http://getnikola.com" rel="nofollow">Nikola</a> \ + <a href="https://getnikola.com" rel="nofollow">Nikola</a> \ {license}' # Things that will be passed to CONTENT_FOOTER.format(). This is done @@ -443,8 +635,8 @@ COMMENT_SYSTEM_ID = ${COMMENT_SYSTEM_ID} # the "noannotations" metadata. # ANNOTATIONS = False -# Create index.html for story folders? -# WARNING: if a story would conflict with the index file (usually +# Create index.html for page (story) folders? +# WARNING: if a page would conflict with the index file (usually # caused by setting slug to `index`), the STORY_INDEX # will not be generated for that directory. # STORY_INDEX = False @@ -480,12 +672,12 @@ COMMENT_SYSTEM_ID = ${COMMENT_SYSTEM_ID} # /robots.txt and /sitemap.xml, and to inform search engines about /sitemapindex.xml. # ROBOTS_EXCLUSIONS = ["/archive.html", "/category/*.html"] -# Instead of putting files in <slug>.html, put them in -# <slug>/index.html. Also enables STRIP_INDEXES +# Instead of putting files in <slug>.html, put them in <slug>/index.html. +# No web server configuration is required. Also enables STRIP_INDEXES. # This can be disabled on a per-page/post basis by adding # .. pretty_url: False -# to the metadata -# PRETTY_URLS = False +# to the metadata. +PRETTY_URLS = ${PRETTY_URLS} # If True, publish future dated posts right away instead of scheduling them. # Defaults to False. @@ -513,7 +705,8 @@ COMMENT_SYSTEM_ID = ${COMMENT_SYSTEM_ID} # MathJax.Hub.Config({ # tex2jax: { # inlineMath: [ ['$','$'], ["\\\(","\\\)"] ], -# displayMath: [ ['$$','$$'], ["\\\[","\\\]"] ] +# displayMath: [ ['$$','$$'], ["\\\[","\\\]"] ], +# processEscapes: true # }, # displayAlign: 'left', // Change this to 'center' to center equations. # "HTML-CSS": { @@ -525,7 +718,7 @@ COMMENT_SYSTEM_ID = ${COMMENT_SYSTEM_ID} # Do you want to customize the nbconversion of your IPython notebook? # IPYNB_CONFIG = {} -# With the following example configuracion you can use a custom jinja template +# With the following example configuration you can use a custom jinja template # called `toggle.tpl` which has to be located in your site/blog main folder: # IPYNB_CONFIG = {'Exporter':{'template_file': 'toggle'}} @@ -534,10 +727,17 @@ COMMENT_SYSTEM_ID = ${COMMENT_SYSTEM_ID} # done in the code, hope you don't mind ;-) # Note: most Nikola-specific extensions are done via the Nikola plugin system, # with the MarkdownExtension class and should not be added here. -# MARKDOWN_EXTENSIONS = ['fenced_code', 'codehilite'] +# The default is ['fenced_code', 'codehilite'] +MARKDOWN_EXTENSIONS = ['fenced_code', 'codehilite', 'extra'] + +# Extra options to pass to the pandoc comand. +# by default, it's empty, is a list of strings, for example +# ['-F', 'pandoc-citeproc', '--bibliography=/Users/foo/references.bib'] +# PANDOC_OPTIONS = [] # Social buttons. This is sample code for AddThis (which was the default for a -# long time). Insert anything you want here, or even make it empty. +# long time). Insert anything you want here, or even make it empty (which is +# the default right now) # (translatable) # SOCIAL_BUTTONS_CODE = """ # <!-- Social buttons --> @@ -568,20 +768,29 @@ COMMENT_SYSTEM_ID = ${COMMENT_SYSTEM_ID} # links to it. Set this to False to disable everything RSS-related. # GENERATE_RSS = True +# By default, Nikola does not generates Atom files for indexes and links to +# them. Generate Atom for tags by setting TAG_PAGES_ARE_INDEXES to True. +# Atom feeds are built based on INDEX_DISPLAY_POST_COUNT and not FEED_LENGTH +# Switch between plain-text summaries and full HTML content using the +# RSS_TEASER option. RSS_LINKS_APPEND_QUERY is also respected. Atom feeds +# are generated even for old indexes and have pagination link relations +# between each other. Old Atom feeds with no changes are marked as archived. +# GENERATE_ATOM = False + # RSS_LINK is a HTML fragment to link the RSS or Atom feeds. If set to None, # the base.tmpl will use the feed Nikola generates. However, you may want to -# change it for a feedburner feed or something else. +# change it for a FeedBurner feed or something else. # RSS_LINK = None -# Show only teasers in the RSS feed? Default to True +# Show only teasers in the RSS and Atom feeds? Default to True # RSS_TEASERS = True # Strip HTML in the RSS feed? Default to False # RSS_PLAIN = False -# A search form to search this site, for the sidebar. You can use a google +# A search form to search this site, for the sidebar. You can use a Google # custom search (http://www.google.com/cse/) -# Or a duckduckgo search: https://duckduckgo.com/search_box.html +# Or a DuckDuckGo search: https://duckduckgo.com/search_box.html # Default is no search form. # (translatable) # SEARCH_FORM = "" @@ -604,9 +813,9 @@ COMMENT_SYSTEM_ID = ${COMMENT_SYSTEM_ID} # <!-- End of custom search --> # """ % SITE_URL # -# If you prefer a google search form, here's an example that should just work: +# If you prefer a Google search form, here's an example that should just work: # SEARCH_FORM = """ -# <!-- Custom search with google--> +# <!-- Custom search with Google--> # <form id="search" action="//www.google.com/search" method="get" class="navbar-form pull-left"> # <input type="hidden" name="q" value="site:%s" /> # <input type="text" name="q" maxlength="255" results="0" placeholder="Search"/> @@ -614,14 +823,20 @@ COMMENT_SYSTEM_ID = ${COMMENT_SYSTEM_ID} # <!-- End of custom search --> #""" % SITE_URL -# Use content distribution networks for jquery, twitter-bootstrap css and js, +# Use content distribution networks for jQuery, twitter-bootstrap css and js, # and html5shiv (for older versions of Internet Explorer) -# If this is True, jquery and html5shiv is served from the Google and twitter- -# bootstrap is served from the NetDNA CDN +# If this is True, jQuery and html5shiv are served from the Google CDN and +# Bootstrap is served from BootstrapCDN (provided by MaxCDN) # Set this to False if you want to host your site without requiring access to # external resources. # USE_CDN = False +# Check for USE_CDN compatibility. +# If you are using custom themes, have configured the CSS properly and are +# receiving warnings about incompatibility but believe they are incorrect, you +# can set this to False. +# USE_CDN_WARNING = True + # Extra things you want in the pages HEAD tag. This will be added right # before </head> # (translatable) @@ -658,29 +873,28 @@ UNSLUGIFY_TITLES = True # Open Graph is enabled by default. # USE_OPEN_GRAPH = True -# Nikola supports Twitter Card summaries -# Twitter cards are disabled by default. They make it possible for you to -# attach media to Tweets that link to your content. +# Nikola supports Twitter Card summaries, but they are disabled by default. +# They make it possible for you to attach media to Tweets that link +# to your content. # # IMPORTANT: # Please note, that you need to opt-in for using Twitter Cards! -# To do this please visit -# https://dev.twitter.com/form/participate-twitter-cards +# To do this please visit https://cards-dev.twitter.com/validator # # Uncomment and modify to following lines to match your accounts. -# Specifying the id for either 'site' or 'creator' will be preferred -# over the cleartext username. Specifying an ID is not necessary. -# Displaying images is currently not supported. +# Images displayed come from the `previewimage` meta tag. +# You can specify the card type by using the `card` parameter in TWITTER_CARD. # TWITTER_CARD = { # # 'use_twitter_cards': True, # enable Twitter Cards -# # 'site': '@website', # twitter nick for the website -# # 'site:id': 123456, # Same as site, but the website's Twitter user ID -# # instead. -# # 'creator': '@username', # Username for the content creator / author. -# # 'creator:id': 654321, # Same as creator, but the Twitter user's ID. +# # 'card': 'summary', # Card type, you can also use 'summary_large_image', +# # see https://dev.twitter.com/cards/types +# # 'site': '@website', # twitter nick for the website +# # 'creator': '@username', # Username for the content creator / author. # } -# If webassets is installed, bundle JS and CSS to make site loading faster +# If webassets is installed, bundle JS and CSS into single files to make +# site loading faster in a HTTP/1.1 environment but is not recommended for +# HTTP/2.0 when caching is used. Defaults to True. # USE_BUNDLES = True # Plugins you don't want to use. Be careful :-) @@ -740,3 +954,8 @@ LOGGING_HANDLERS = { # Put in global_context things you want available on all your templates. # It can be anything, data, functions, modules, etc. GLOBAL_CONTEXT = {} + +# Add functions here and they will be called with template +# GLOBAL_CONTEXT as parameter when the template is about to be +# rendered +GLOBAL_CONTEXT_FILLER = [] diff --git a/nikola/data/samplesite/README.txt b/nikola/data/samplesite/README.txt index aeea39c..da0d685 100644 --- a/nikola/data/samplesite/README.txt +++ b/nikola/data/samplesite/README.txt @@ -1,6 +1,6 @@ -This folder contains the source used to generate a static site by nikola. +This folder contains the source used to generate a static site using Nikola. -Installation and documentation at http://getnikola.com +Installation and documentation at https://getnikola.com/ Configuration file for the site is `conf.py`. @@ -12,7 +12,7 @@ To see it:: nikola serve -And point your browser to http://localhost:8000 +And point your browser to http://localhost:8000/ To check all available commands:: diff --git a/nikola/data/samplesite/posts/1.rst b/nikola/data/samplesite/posts/1.rst index 7116a7a..9a55859 100644 --- a/nikola/data/samplesite/posts/1.rst +++ b/nikola/data/samplesite/posts/1.rst @@ -3,22 +3,25 @@ .. date: 2012-03-30 23:00:00 UTC-03:00 .. tags: nikola, python, demo, blog .. author: Roberto Alsina -.. link: http://getnikola.com +.. link: https://getnikola.com/ .. description: +.. category: nikola .. figure:: http://farm1.staticflickr.com/138/352972944_4f9d568680.jpg :target: http://farm1.staticflickr.com/138/352972944_4f9d568680_z.jpg?zz=1 :class: thumbnail :alt: Nikola Tesla Corner by nicwest, on Flickr -If you can see this in a web browser, it means you have managed to install Nikola, +If you can see this in a web browser, it means you managed to install Nikola, and build a site using it. Congratulations! -* You can read the manual `here </stories/handbook.html>`__ -* You can learn more about Nikola at http://getnikola.com -* You can see a demo photo gallery `here </galleries/demo/index.html>`__ -* Demo usage of listings `here </stories/listings-demo.html>`__ -* Demo of slideshows `here </stories/slides-demo.html>`__ -* Demo of Bootstrap `here </stories/bootstrap-demo.html>`__ +Next steps: -Send feedback to ralsina@netmanagers.com.ar! +* `Read the manual </stories/handbook.html>`__ +* `Visit the Nikola website to learn more <https://getnikola.com>`__ +* `See a demo photo gallery </galleries/demo/index.html>`__ +* `See a demo listing </stories/listings-demo.html>`__ +* `See a demo slideshow </stories/slides-demo.html>`__ +* `See a demo of the Bootstrap theme </stories/bootstrap-demo.html>`__ + +Send feedback to info@getnikola.com! diff --git a/nikola/data/samplesite/stories/1.rst b/nikola/data/samplesite/stories/1.rst index b662fae..abe1d0b 100644 --- a/nikola/data/samplesite/stories/1.rst +++ b/nikola/data/samplesite/stories/1.rst @@ -7,5 +7,5 @@ Hope you enjoy this software! -* Home page at http://getnikola.com -* Author's blog (and reason why Nikola exists): http://ralsina.me +* Home page at https://getnikola.com/ +* Author's blog (and reason why Nikola exists): http://ralsina.me/ diff --git a/nikola/data/samplesite/stories/bootstrap-demo.rst b/nikola/data/samplesite/stories/bootstrap-demo.rst index a7be1a9..481140a 100644 --- a/nikola/data/samplesite/stories/bootstrap-demo.rst +++ b/nikola/data/samplesite/stories/bootstrap-demo.rst @@ -2,7 +2,7 @@ .. slug: bootstrap-demo .. date: 2012-03-30 23:00:00 UTC-03:00 .. tags: bootstrap, demo -.. link: http://getnikola.com +.. link: https://getnikola.com .. description: diff --git a/nikola/data/samplesite/stories/upgrading-to-v6.txt b/nikola/data/samplesite/stories/upgrading-to-v6.txt deleted file mode 120000 index b514b70..0000000 --- a/nikola/data/samplesite/stories/upgrading-to-v6.txt +++ /dev/null @@ -1 +0,0 @@ -../../../../docs/upgrading-to-v6.txt
\ No newline at end of file diff --git a/nikola/data/symlink-test-link.txt b/nikola/data/symlink-test-link.txt new file mode 120000 index 0000000..bd0f6c1 --- /dev/null +++ b/nikola/data/symlink-test-link.txt @@ -0,0 +1 @@ +symlink-test-orig.txt
\ No newline at end of file diff --git a/nikola/data/symlink-test-orig.txt b/nikola/data/symlink-test-orig.txt new file mode 100644 index 0000000..6242bf3 --- /dev/null +++ b/nikola/data/symlink-test-orig.txt @@ -0,0 +1,4 @@ +NIKOLA_SYMLINKS=OK + +This is a test file for symlink detection, used to test compatibility with +Microsoft Windows. diff --git a/nikola/data/symlinked.txt b/nikola/data/symlinked.txt index 5a08781..aae8ea1 100644 --- a/nikola/data/symlinked.txt +++ b/nikola/data/symlinked.txt @@ -5,29 +5,21 @@ docs/sphinx/internals.txt docs/sphinx/manual.txt docs/sphinx/social_buttons.txt docs/sphinx/theming.txt -docs/sphinx/upgrading-to-v6.txt nikola/data/samplesite/stories/creating-a-theme.rst nikola/data/samplesite/stories/extending.txt nikola/data/samplesite/stories/internals.txt nikola/data/samplesite/stories/manual.rst nikola/data/samplesite/stories/social_buttons.txt nikola/data/samplesite/stories/theming.rst -nikola/data/samplesite/stories/upgrading-to-v6.txt +nikola/data/symlink-test-link.txt +nikola/data/themes/base/assets/js/moment-with-locales.min.js nikola/data/themes/base/messages/messages_cz.py -nikola/data/themes/bootstrap-jinja/assets/css/bootstrap-responsive.css -nikola/data/themes/bootstrap-jinja/assets/css/bootstrap-responsive.min.css -nikola/data/themes/bootstrap-jinja/assets/css/bootstrap.css -nikola/data/themes/bootstrap-jinja/assets/css/bootstrap.min.css nikola/data/themes/bootstrap-jinja/assets/css/colorbox.css nikola/data/themes/bootstrap-jinja/assets/css/images/controls.png nikola/data/themes/bootstrap-jinja/assets/css/images/loading.gif -nikola/data/themes/bootstrap-jinja/assets/css/theme.css -nikola/data/themes/bootstrap-jinja/assets/img/glyphicons-halflings-white.png -nikola/data/themes/bootstrap-jinja/assets/img/glyphicons-halflings.png -nikola/data/themes/bootstrap-jinja/assets/js/bootstrap.js -nikola/data/themes/bootstrap-jinja/assets/js/bootstrap.min.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-ar.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-bg.js +nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-bn.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-ca.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-cs.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-da.js @@ -52,7 +44,7 @@ nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-my.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-nl.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-no.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-pl.js -nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-pt-br.js +nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-pt-BR.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-ro.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-ru.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-si.js @@ -63,9 +55,9 @@ nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-tr.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-uk.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-zh-CN.js nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-zh-TW.js -nikola/data/themes/bootstrap-jinja/assets/js/flowr.plugin.js nikola/data/themes/bootstrap-jinja/assets/js/jquery.colorbox-min.js nikola/data/themes/bootstrap-jinja/assets/js/jquery.colorbox.js +nikola/data/themes/bootstrap-jinja/assets/js/jquery.js nikola/data/themes/bootstrap-jinja/assets/js/jquery.min.js nikola/data/themes/bootstrap-jinja/assets/js/jquery.min.map nikola/data/themes/bootstrap-jinja/bundles @@ -74,6 +66,7 @@ nikola/data/themes/bootstrap/assets/css/images/controls.png nikola/data/themes/bootstrap/assets/css/images/loading.gif nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-ar.js nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-bg.js +nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-bn.js nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-ca.js nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-cs.js nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-da.js @@ -98,7 +91,7 @@ nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-my.js nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-nl.js nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-no.js nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-pl.js -nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-pt-br.js +nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-pt-BR.js nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-ro.js nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-ru.js nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-si.js @@ -111,6 +104,7 @@ nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-zh-CN.js nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-zh-TW.js nikola/data/themes/bootstrap/assets/js/jquery.colorbox-min.js nikola/data/themes/bootstrap/assets/js/jquery.colorbox.js +nikola/data/themes/bootstrap/assets/js/jquery.js nikola/data/themes/bootstrap/assets/js/jquery.min.js nikola/data/themes/bootstrap/assets/js/jquery.min.map nikola/data/themes/bootstrap3-jinja/assets/css/bootstrap-theme.css @@ -119,21 +113,11 @@ nikola/data/themes/bootstrap3-jinja/assets/css/bootstrap-theme.min.css nikola/data/themes/bootstrap3-jinja/assets/css/bootstrap.css nikola/data/themes/bootstrap3-jinja/assets/css/bootstrap.css.map nikola/data/themes/bootstrap3-jinja/assets/css/bootstrap.min.css -nikola/data/themes/bootstrap3-jinja/assets/css/docs.css -nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomCenter.png -nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomLeft.png -nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomRight.png -nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderMiddleLeft.png -nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderMiddleRight.png -nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopCenter.png -nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopLeft.png -nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopRight.png -nikola/data/themes/bootstrap3-jinja/assets/css/rst.css -nikola/data/themes/bootstrap3-jinja/assets/css/theme.css nikola/data/themes/bootstrap3-jinja/assets/fonts/glyphicons-halflings-regular.eot nikola/data/themes/bootstrap3-jinja/assets/fonts/glyphicons-halflings-regular.svg nikola/data/themes/bootstrap3-jinja/assets/fonts/glyphicons-halflings-regular.ttf nikola/data/themes/bootstrap3-jinja/assets/fonts/glyphicons-halflings-regular.woff +nikola/data/themes/bootstrap3-jinja/assets/fonts/glyphicons-halflings-regular.woff2 nikola/data/themes/bootstrap3-jinja/assets/js/bootstrap.js nikola/data/themes/bootstrap3-jinja/assets/js/bootstrap.min.js nikola/data/themes/bootstrap3-jinja/bundles @@ -147,5 +131,7 @@ nikola/data/themes/bootstrap3/assets/fonts/glyphicons-halflings-regular.eot nikola/data/themes/bootstrap3/assets/fonts/glyphicons-halflings-regular.svg nikola/data/themes/bootstrap3/assets/fonts/glyphicons-halflings-regular.ttf nikola/data/themes/bootstrap3/assets/fonts/glyphicons-halflings-regular.woff +nikola/data/themes/bootstrap3/assets/fonts/glyphicons-halflings-regular.woff2 nikola/data/themes/bootstrap3/assets/js/bootstrap.js nikola/data/themes/bootstrap3/assets/js/bootstrap.min.js +nikola/plugins/command/auto/livereload.js diff --git a/nikola/data/themes/base-jinja/templates/archiveindex.tmpl b/nikola/data/themes/base-jinja/templates/archiveindex.tmpl new file mode 100644 index 0000000..565732c --- /dev/null +++ b/nikola/data/themes/base-jinja/templates/archiveindex.tmpl @@ -0,0 +1,13 @@ +{# -*- coding: utf-8 -*- #} +{% extends 'index.tmpl' %} + +{% block extra_head %} + {{ super() }} + {% if translations|length > 1 and generate_atom %} + {% for language in translations %} + <link rel="alternate" type="application/atom+xml" title="Atom for the {{ archive_name }} section ({{ language }})" href="{{ _link("archive_atom", archive_name, language) }}"> + {% endfor %} + {% elif generate_atom %} + <link rel="alternate" type="application/atom+xml" title="Atom for the {{ archive_name }} archive" href="{{ _link("archive_atom", archive_name) }}"> + {% endif %} +{% endblock %} diff --git a/nikola/data/themes/base-jinja/templates/base.tmpl b/nikola/data/themes/base-jinja/templates/base.tmpl index 3768b9e..00ba9d7 100644 --- a/nikola/data/themes/base-jinja/templates/base.tmpl +++ b/nikola/data/themes/base-jinja/templates/base.tmpl @@ -14,7 +14,7 @@ <a href="#content" class="sr-only sr-only-focusable">{{ messages("Skip to main content") }}</a> <div id="container"> {{ header.html_header() }} - <main id="content"> + <main id="content" role="main"> {% block content %}{% endblock %} </main> {{ footer.html_footer() }} diff --git a/nikola/data/themes/base-jinja/templates/base_header.tmpl b/nikola/data/themes/base-jinja/templates/base_header.tmpl index 7947f68..9f79e72 100644 --- a/nikola/data/themes/base-jinja/templates/base_header.tmpl +++ b/nikola/data/themes/base-jinja/templates/base_header.tmpl @@ -16,7 +16,7 @@ {% endmacro %} {% macro html_site_title() %} - <h1 id="brand"><a href="{{ abs_link('/') }}" title="{{ blog_title }}" rel="home"> + <h1 id="brand"><a href="{{ abs_link(_link("root", None, lang)) }}" title="{{ blog_title }}" rel="home"> {% if logo_url %} <img src="{{ logo_url }}" alt="{{ blog_title }}" id="logo"> {% endif %} @@ -36,7 +36,7 @@ <ul> {% for suburl, text in url %} {% if rel_link(permalink, suburl) == "#" %} - <li class="active"><a href="{{ permalink }}">{{ text }}</a></li> + <li class="active"><a href="{{ permalink }}">{{ text }} <span class="sr-only">{{ messages("(active)", lang) }}</span></a></li> {% else %} <li><a href="{{ suburl }}">{{ text }}</a></li> {% endif %} @@ -44,7 +44,7 @@ </ul> {% else %} {% if rel_link(permalink, url) == "#" %} - <li class="active"><a href="{{ permalink }}">{{ text }}</a></li> + <li class="active"><a href="{{ permalink }}">{{ text }} <span class="sr-only">{{ messages("(active)", lang) }}</span></a></li> {% else %} <li><a href="{{ url }}">{{ text }}</a></li> {% endif %} diff --git a/nikola/data/themes/base-jinja/templates/base_helper.tmpl b/nikola/data/themes/base-jinja/templates/base_helper.tmpl index bd5d025..baa6810 100644 --- a/nikola/data/themes/base-jinja/templates/base_helper.tmpl +++ b/nikola/data/themes/base-jinja/templates/base_helper.tmpl @@ -2,28 +2,24 @@ {% macro html_headstart() %} <!DOCTYPE html> -<html - -{% if use_open_graph or (twitter_card and twitter_card['use_twitter_cards']) or (comment_system == 'facebook') %} +<html \ prefix=' {% if use_open_graph or (twitter_card and twitter_card['use_twitter_cards']) %} -og: http://ogp.me/ns# -{% endif %} -{% if use_open_graph %} -article: http://ogp.me/ns/article# +og: http://ogp.me/ns# article: http://ogp.me/ns/article# {% endif %} {% if comment_system == 'facebook' %} fb: http://ogp.me/ns/fb# {% endif %} -' +' \ +{% if use_open_graph or (twitter_card and twitter_card['use_twitter_cards']) %} +vocab="http://ogp.me/ns" \ {% endif %} - {% if is_rtl %} dir="rtl" {% endif %} lang="{{ lang }}"> - <head> +<head> <meta charset="utf-8"> {% if description %} <meta name="description" content="{{ description }}"> @@ -83,6 +79,10 @@ lang="{{ lang }}"> <link href="/assets/css/custom.css" rel="stylesheet" type="text/css"> {% endif %} {% endif %} + {% if needs_ipython_css %} + <link href="/assets/css/ipython.min.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/nikola_ipython.css" rel="stylesheet" type="text/css"> + {% endif %} {% endmacro %} {% macro html_feedlinks() %} @@ -97,13 +97,22 @@ lang="{{ lang }}"> <link rel="alternate" type="application/rss+xml" title="RSS" href="{{ _link('rss', None) }}"> {% endif %} {% endif %} + {% if generate_atom %} + {% if translations|length > 1 %} + {% for language in translations %} + <link rel="alternate" type="application/atom+xml" title="Atom ({{ language }})" href="{{ _link('index_atom', None, language) }}"> + {% endfor %} + {% else %} + <link rel="alternate" type="application/atom+xml" title="Atom" href="{{ _link('index_atom', None) }}"> + {% endif %} + {% endif %} {% endmacro %} {% macro html_translations() %} <ul class="translations"> {% for langname in translations.keys() %} {% if langname != lang %} - <li><a href="{{ _link("index", None, langname) }}" rel="alternate" hreflang="{{ langname }}">{{ messages("LANGUAGE", langname) }}</a></li> + <li><a href="{{ abs_link(_link("root", None, langname)) }}" rel="alternate" hreflang="{{ langname }}">{{ messages("LANGUAGE", langname) }}</a></li> {% endif %} {% endfor %} </ul> diff --git a/nikola/data/themes/base-jinja/templates/comments_helper_disqus.tmpl b/nikola/data/themes/base-jinja/templates/comments_helper_disqus.tmpl index 8288bd4..0d40b0b 100644 --- a/nikola/data/themes/base-jinja/templates/comments_helper_disqus.tmpl +++ b/nikola/data/themes/base-jinja/templates/comments_helper_disqus.tmpl @@ -1,10 +1,4 @@ {# -*- coding: utf-8 -*- #} -<%! - import json - translations = { - 'es': 'es_ES', - } -%> {% macro comment_form(url, title, identifier) %} {% if comment_system_id %} @@ -17,7 +11,11 @@ disqus_title={{ title|tojson }}, disqus_identifier="{{ identifier }}", disqus_config = function () { - this.language = "{{ translations.get(lang, lang) }}"; + {% if lang == 'es' %} + this.language = "es_ES"; + {% else %} + this.language = "{{ lang }}"; + {% endif %} }; (function() { var dsq = document.createElement('script'); dsq.async = true; diff --git a/nikola/data/themes/base-jinja/templates/crumbs.tmpl b/nikola/data/themes/base-jinja/templates/crumbs.tmpl index eede9c2..970d509 100644 --- a/nikola/data/themes/base-jinja/templates/crumbs.tmpl +++ b/nikola/data/themes/base-jinja/templates/crumbs.tmpl @@ -5,7 +5,13 @@ <nav class="breadcrumbs"> <ul class="breadcrumb"> {% for link, text in crumbs %} - <li><a href="{{ link }}">{{ text }}</a></li> + {% if text != index_file %} + {% if link == '#' %} + <li>{{ text.rsplit('.html', 1)[0] }}</li> + {% else %} + <li><a href="{{ link }}">{{ text }}</a></li> + {% endif %} + {% endif %} {% endfor %} </ul> </nav> diff --git a/nikola/data/themes/base-jinja/templates/gallery.tmpl b/nikola/data/themes/base-jinja/templates/gallery.tmpl index 86eea12..0a53ebe 100644 --- a/nikola/data/themes/base-jinja/templates/gallery.tmpl +++ b/nikola/data/themes/base-jinja/templates/gallery.tmpl @@ -7,7 +7,7 @@ {% block content %} {{ ui.bar(crumbs) }} {% if title %} - <h1>{{ title }}</h1> + <h1>{{ title|e }}</h1> {% endif %} {% if post %} <p> @@ -34,3 +34,8 @@ {{ comments.comment_form(None, permalink, title) }} {% endif %} {% endblock %} + +{% block extra_head %} +{{ super() }} +<link rel="alternate" type="application/rss+xml" title="RSS" href="rss.xml"> +{% endblock %} diff --git a/nikola/data/themes/base-jinja/templates/index.tmpl b/nikola/data/themes/base-jinja/templates/index.tmpl index 206fc34..fd9fcf4 100644 --- a/nikola/data/themes/base-jinja/templates/index.tmpl +++ b/nikola/data/themes/base-jinja/templates/index.tmpl @@ -3,15 +3,23 @@ {% import 'comments_helper.tmpl' as comments with context %} {% extends 'base.tmpl' %} +{% block extra_head %} + {{ super() }} + {% if posts and (permalink == '/' or permalink == '/' + index_file) %} + <link rel="prefetch" href="{{ posts[0].permalink() }}" type="text/html"> + {% endif %} +{% endblock %} + {% block content %} +{% block content_header %}{% endblock %} <div class="postindex"> {% for post in posts %} <article class="h-entry post-{{ post.meta('type') }}"> <header> - <h1 class="p-name entry-title"><a href="{{ post.permalink() }}" class="u-url">{{ post.title() }}</h1></a> + <h1 class="p-name entry-title"><a href="{{ post.permalink() }}" class="u-url">{{ post.title()|e }}</a></h1> <div class="metadata"> <p class="byline author vcard"><span class="byline-name fn">{{ post.author() }}</span></p> - <p class="dateline"><a href="{{ post.permalink() }}" rel="bookmark"><time class="published dt-published" datetime="{{ post.date.isoformat() }}" itemprop="datePublished" title="{{ messages("Publication date") }}">{{ post.formatted_date(date_format) }}</time></a></p> + <p class="dateline"><a href="{{ post.permalink() }}" rel="bookmark"><time class="published dt-published" datetime="{{ post.date.isoformat() }}" title="{{ post.formatted_date(date_format) }}">{{ post.formatted_date(date_format) }}</time></a></p> {% if not post.meta('nocomments') and site_has_comments %} <p class="commentline">{{ comments.comment_link(post.permalink(), post._base_path) }} {% endif %} diff --git a/nikola/data/themes/base-jinja/templates/list_post.tmpl b/nikola/data/themes/base-jinja/templates/list_post.tmpl index b90f237..166d8c4 100644 --- a/nikola/data/themes/base-jinja/templates/list_post.tmpl +++ b/nikola/data/themes/base-jinja/templates/list_post.tmpl @@ -9,7 +9,7 @@ {% if posts %} <ul class="postlist"> {% for post in posts %} - <li><a href="{{ post.permalink() }}" class="listtitle">{{ post.title() }}</a> <time class="listdate" datetime="{{ post.date.isoformat() }}" title="{{ messages("Publication date") }}">{{ post.formatted_date(date_format) }}</time></li> + <li><a href="{{ post.permalink() }}" class="listtitle">{{ post.title()|e }}</a> <time class="listdate" datetime="{{ post.date.isoformat() }}" title="{{ post.formatted_date(date_format) }}">{{ post.formatted_date(date_format) }}</time></li> {% endfor %} </ul> {% else %} diff --git a/nikola/data/themes/base-jinja/templates/post.tmpl b/nikola/data/themes/base-jinja/templates/post.tmpl index e6dc97b..28da35e 100644 --- a/nikola/data/themes/base-jinja/templates/post.tmpl +++ b/nikola/data/themes/base-jinja/templates/post.tmpl @@ -10,14 +10,17 @@ <meta name="keywords" content="{{ post.meta('keywords')|e }}"> {% endif %} {% if post.description() %} - <meta name="description" itemprop="description" content="{{ post.description() }}"> + <meta name="description" content="{{ post.description() }}"> {% endif %} <meta name="author" content="{{ post.author() }}"> {% if post.prev_post %} - <link rel="prev" href="{{ post.prev_post.permalink() }}" title="{{ post.prev_post.title() }}" type="text/html"> + <link rel="prev" href="{{ post.prev_post.permalink() }}" title="{{ post.prev_post.title()|e }}" type="text/html"> {% endif %} {% if post.next_post %} - <link rel="next" href="{{ post.next_post.permalink() }}" title="{{ post.next_post.title() }}" type="text/html"> + <link rel="next" href="{{ post.next_post.permalink() }}" title="{{ post.next_post.title()|e }}" type="text/html"> + {% endif %} + {% if post.is_draft %} + <meta name="robots" content="noindex"> {% endif %} {{ helper.open_graph_metadata(post) }} {{ helper.twitter_card_information(post) }} @@ -37,7 +40,7 @@ </nav> </aside> {% if not post.meta('nocomments') and site_has_comments %} - <section class="comments"> + <section class="comments hidden-print"> <h2>{{ messages("Comments") }}</h2> {{ comments.comment_form(post.permalink(absolute=True), post.title(), post._base_path) }} </section> diff --git a/nikola/data/themes/base-jinja/templates/post_header.tmpl b/nikola/data/themes/base-jinja/templates/post_header.tmpl index 0ed40b9..00b6210 100644 --- a/nikola/data/themes/base-jinja/templates/post_header.tmpl +++ b/nikola/data/themes/base-jinja/templates/post_header.tmpl @@ -4,12 +4,12 @@ {% macro html_title() %} {% if title and not post.meta('hidetitle') %} - <h1 class="p-name entry-title" itemprop="headline name"><a href="{{ post.permalink() }}" class="u-url">{{ title|e }}</a></h1> + <h1 class="p-name entry-title" itemprop="headline name"><a href="{{ post.permalink() }}" class="u-url">{{ post.title()|e }}</a></h1> {% endif %} {% endmacro %} {% macro html_translations(post) %} - {% if translations|length > 1 %} + {% if post.translated_to|length > 1 %} <div class="metadata posttranslations translations"> <h3 class="posttranslations-intro">{{ messages("Also available in:") }}</h3> {% for langname in translations.keys() %} @@ -32,13 +32,13 @@ {{ html_title() }} <div class="metadata"> <p class="byline author vcard"><span class="byline-name fn">{{ post.author() }}</span></p> - <p class="dateline"><a href="{{ post.permalink() }}" rel="bookmark"><time class="published dt-published" datetime="{{ post.date.isoformat() }}" itemprop="datePublished" title="{{ messages("Publication date") }}">{{ post.formatted_date(date_format) }}</time></a></p> + <p class="dateline"><a href="{{ post.permalink() }}" rel="bookmark"><time class="published dt-published" datetime="{{ post.date.isoformat() }}" itemprop="datePublished" title="{{ post.formatted_date(date_format) }}">{{ post.formatted_date(date_format) }}</time></a></p> {% if not post.meta('nocomments') and site_has_comments %} <p class="commentline">{{ comments.comment_link(post.permalink(), post._base_path) }} {% endif %} {{ html_sourcelink() }} {% if post.meta('link') %} - <p><a href='{{ post.meta('link') }}'>{{ messages("Original site") }}</a></p> + <p class="linkline"><a href='{{ post.meta('link') }}'>{{ messages("Original site") }}</a></p> {% endif %} {% if post.description() %} <meta name="description" itemprop="description" content="{{ post.description() }}"> diff --git a/nikola/data/themes/base-jinja/templates/post_helper.tmpl b/nikola/data/themes/base-jinja/templates/post_helper.tmpl index 541cd31..ae0206b 100644 --- a/nikola/data/themes/base-jinja/templates/post_helper.tmpl +++ b/nikola/data/themes/base-jinja/templates/post_helper.tmpl @@ -14,7 +14,9 @@ {% if post.tags %} <ul itemprop="keywords" class="tags"> {% for tag in post.tags %} - <li><a class="tag p-category" href="{{ _link('tag', tag) }}" rel="tag">{{ tag }}</a></li> + {% if tag not in hidden_tags %} + <li><a class="tag p-category" href="{{ _link('tag', tag) }}" rel="tag">{{ tag }}</a></li> + {% endif %} {% endfor %} </ul> {% endif %} @@ -22,15 +24,15 @@ {% macro html_pager(post) %} {% if post.prev_post or post.next_post %} - <ul class="pager"> + <ul class="pager hidden-print"> {% if post.prev_post %} <li class="previous"> - <a href="{{ post.prev_post.permalink() }}" rel="prev" title="{{ post.prev_post.title() }}">{{ messages("Previous post") }}</a> + <a href="{{ post.prev_post.permalink() }}" rel="prev" title="{{ post.prev_post.title()|e }}">{{ messages("Previous post") }}</a> </li> {% endif %} {% if post.next_post %} <li class="next"> - <a href="{{ post.next_post.permalink() }}" rel="next" title="{{ post.next_post.title() }}">{{ messages("Next post") }}</a> + <a href="{{ post.next_post.permalink() }}" rel="next" title="{{ post.next_post.title()|e }}">{{ messages("Next post") }}</a> </li> {% endif %} </ul> @@ -39,15 +41,30 @@ {% macro open_graph_metadata(post) %} {% if use_open_graph %} - <meta name="og:title" content="{{ post.title()[:70]|e }}"> - <meta name="og:url" content="{{ abs_link(permalink) }}"> + <meta property="og:site_name" content="{{ blog_title|e }}"> + <meta property="og:title" content="{{ post.title()[:70]|e }}"> + <meta property="og:url" content="{{ abs_link(permalink) }}"> {% if post.description() %} - <meta name="og:description" content="{{ post.description()[:200]|e }}"> + <meta property="og:description" content="{{ post.description()[:200]|e }}"> {% else %} - <meta name="og:description" content="{{ post.text(strip_html=True)[:200]|e }}"> + <meta property="og:description" content="{{ post.text(strip_html=True)[:200]|e }}"> + {% endif %} + {% if post.previewimage %} + <meta property="og:image" content="{{ url_replacer(permalink, post.previewimage, lang, 'absolute') }}"> + {% endif %} + <meta property="og:type" content="article"> +{# Will only work with Pintrest and breaks everywhere else who expect a [Facebook] URI. #} +{# %if post.author(): #} +{# <meta property="article:author" content="{{ post.author() }}"> #} +{# %endif #} + {% if post.date.isoformat() %} + <meta property="article:published_time" content="{{ post.date.isoformat() }}"> + {% endif %} + {% if post.tags %} + {% for tag in post.tags %} + <meta property="article:tag" content="{{ tag }}"> + {% endfor %} {% endif %} - <meta name="og:site_name" content="{{ blog_title|e }}"> - <meta name="og:type" content="article"> {% endif %} {% endmacro %} diff --git a/nikola/data/themes/base-jinja/templates/post_list_directive.tmpl b/nikola/data/themes/base-jinja/templates/post_list_directive.tmpl index ceaec3f..92c1b7d 100644 --- a/nikola/data/themes/base-jinja/templates/post_list_directive.tmpl +++ b/nikola/data/themes/base-jinja/templates/post_list_directive.tmpl @@ -8,7 +8,7 @@ <li class="post-list-item"> {{ post.formatted_date(date_format) }} - <a href="{{ post.permalink(lang) }}">{{ post.title(lang) }}</a> + <a href="{{ post.permalink(lang) }}">{{ post.title(lang)|e }}</a> </li> {% endfor %} </ul> diff --git a/nikola/data/themes/base-jinja/templates/tag.tmpl b/nikola/data/themes/base-jinja/templates/tag.tmpl index 84f9e68..765c122 100644 --- a/nikola/data/themes/base-jinja/templates/tag.tmpl +++ b/nikola/data/themes/base-jinja/templates/tag.tmpl @@ -16,7 +16,18 @@ {% block content %} <article class="tagpage"> <header> - <h1>{{ title }}</h1> + <h1>{{ title|e }}</h1> + {% if description %} + <p>{{ description }}</p> + {% endif %} + {% if subcategories %} + {{ messages('Subcategories:') }} + <ul> + {% for name, link in subcategories %} + <li><a href="{{ link }}">{{ name }}</a></li> + {% endfor %} + </ul> + {% endif %} <div class="metadata"> {% if translations|length > 1 and generate_rss %} {% for language in translations %} @@ -32,7 +43,7 @@ {% if posts %} <ul class="postlist"> {% for post in posts %} - <li><a href="{{ post.permalink() }}" class="listtitle">{{ post.title() }}</a> <time class="listdate" datetime="{{ post.date.isoformat() }}" title="{{ messages("Publication date") }}">{{ post.formatted_date(date_format) }}</time></li> + <li><a href="{{ post.permalink() }}" class="listtitle">{{ post.title()|e }}</a> <time class="listdate" datetime="{{ post.date.isoformat() }}" title="{{ post.formatted_date(date_format) }}">{{ post.formatted_date(date_format) }}</time></li> {% endfor %} </ul> {% endif %} diff --git a/nikola/data/themes/base-jinja/templates/tagindex.tmpl b/nikola/data/themes/base-jinja/templates/tagindex.tmpl index af0a992..ee7d8b0 100644 --- a/nikola/data/themes/base-jinja/templates/tagindex.tmpl +++ b/nikola/data/themes/base-jinja/templates/tagindex.tmpl @@ -1,2 +1,24 @@ {# -*- coding: utf-8 -*- #} {% extends 'index.tmpl' %} + +{% block content_header %} + {% if subcategories %} + {{ messages('Subcategories:') }} + <ul> + {% for name, link in subcategories %} + <li><a href="{{ link }}">{{ name }}</a></li> + {% endfor %} + </ul> + {% endif %} +{% endblock %} + +{% block extra_head %} + {{ super() }} + {% if translations|length > 1 and generate_atom %} + {% for language in translations %} + <link rel="alternate" type="application/atom+xml" title="Atom for the {{ tag }} section ({{ language }})" href="{{ _link(kind + "_atom", tag, language) }}"> + {% endfor %} + {% elif generate_atom %} + <link rel="alternate" type="application/atom+xml" title="Atom for the {{ tag }} section" href="{{ _link("tag" + "_atom", tag) }}"> + {% endif %} +{% endblock %} diff --git a/nikola/data/themes/base-jinja/templates/tags.tmpl b/nikola/data/themes/base-jinja/templates/tags.tmpl index 7bcb7b2..4605fc9 100644 --- a/nikola/data/themes/base-jinja/templates/tags.tmpl +++ b/nikola/data/themes/base-jinja/templates/tags.tmpl @@ -7,14 +7,24 @@ <h1>{{ title }}</h1> </header> {% if cat_items %} - <h2>{{ messages("Categories") }}</h2> - <ul class="postlist"> - {% for text, link in cat_items %} - {% if text %} - <li><a class="reference" href="{{ link }}">{{ text }}</a></li> + {% if items %} + <h2>{{ messages("Categories") }}</h2> + {% endif %} + {% for text, full_name, path, link, indent_levels, indent_change_before, indent_change_after in cat_hierarchy %} + {% for i in range(indent_change_before) %} + <ul class="postlist"> + {% endfor %} + <li><a class="reference" href="{{ link }}">{{ text }}</a> + {% if indent_change_after <= 0 %} + </li> {% endif %} + {% for i in range(-indent_change_after) %} + </ul> + {% if i + 1 < indent_levels|length %} + </li> + {% endif %} + {% endfor %} {% endfor %} - </ul> {% if items %} <h2>{{ messages("Tags") }}</h2> {% endif %} @@ -22,7 +32,9 @@ {% if items %} <ul class="postlist"> {% for text, link in items %} - <li><a class="reference listtitle" href="{{ link }}">{{ text }}</a></li> + {% if text not in hidden_tags %} + <li><a class="reference listtitle" href="{{ link }}">{{ text }}</a></li> + {% endif %} {% endfor %} </ul> {% endif %} diff --git a/nikola/data/themes/base/assets/css/nikola_ipython.css b/nikola/data/themes/base/assets/css/nikola_ipython.css new file mode 100644 index 0000000..5ae5189 --- /dev/null +++ b/nikola/data/themes/base/assets/css/nikola_ipython.css @@ -0,0 +1,116 @@ +div.prompt { + padding: 0.6em; + font-size: 13px; + background-color: #E9E9E9; + margin-right: 1em; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; +} + +div.output_prompt { + /* 5px right shift to account for margin in parent container */ + margin: 0 5px 0 0px; +} + +div.output_area pre { + font-size: 13px; +} + +div.text_cell_render { + padding: 0px; + color: #333333; +} + +.rendered_html p { + text-align: left; +} + +.rendered_html ul { + margin: 0 0 12px 25px; +} + +.rendered_html :visited { + text-decoration: none; +} + +.rendered_html :link { + text-decoration: none; +} + +.rendered_html pre, .rendered_html code { + background-color: #DDDDDD; + padding-left: 0.5em; + padding-right: 0.5em; + padding-top: 0.05em; + padding-bottom: 0.05em; + margin: 1em 0em; + font-size: 14px; +} + +.page-content > .content p { + margin: 0 0 0px; +} + +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #408080; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #008000; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #BC7A00 } /* Comment.Preproc */ +.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #888888 } /* Generic.Output */ +.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0044DD } /* Generic.Traceback */ +.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #008000 } /* Keyword.Pseudo */ +.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #B00040 } /* Keyword.Type */ +.highlight .m { color: #666666 } /* Literal.Number */ +.highlight .s { color: #BA2121 } /* Literal.String */ +.highlight .na { color: #7D9029 } /* Name.Attribute */ +.highlight .nb { color: #008000 } /* Name.Builtin */ +.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.highlight .no { color: #880000 } /* Name.Constant */ +.highlight .nd { color: #AA22FF } /* Name.Decorator */ +.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #0000FF } /* Name.Function */ +.highlight .nl { color: #A0A000 } /* Name.Label */ +.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #19177C } /* Name.Variable */ +.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #666666 } /* Literal.Number.Float */ +.highlight .mh { color: #666666 } /* Literal.Number.Hex */ +.highlight .mi { color: #666666 } /* Literal.Number.Integer */ +.highlight .mo { color: #666666 } /* Literal.Number.Oct */ +.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ +.highlight .sc { color: #BA2121 } /* Literal.String.Char */ +.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ +.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.highlight .sx { color: #008000 } /* Literal.String.Other */ +.highlight .sr { color: #BB6688 } /* Literal.String.Regex */ +.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ +.highlight .ss { color: #19177C } /* Literal.String.Symbol */ +.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #19177C } /* Name.Variable.Class */ +.highlight .vg { color: #19177C } /* Name.Variable.Global */ +.highlight .vi { color: #19177C } /* Name.Variable.Instance */ +.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ diff --git a/nikola/data/themes/base/assets/css/rst.css b/nikola/data/themes/base/assets/css/rst.css index 784308b..6e6de97 100644 --- a/nikola/data/themes/base/assets/css/rst.css +++ b/nikola/data/themes/base/assets/css/rst.css @@ -253,7 +253,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code { margin-right: 2em } pre.code .ln { color: grey; } /* line numbers */ -pre.code, code { background-color: #eeeeee } +pre.code, code { background-color: #eeeeee; } pre.code .comment, code .comment { color: #5C6576 } pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } pre.code .literal.string, code .literal.string { color: #0C5404 } diff --git a/nikola/data/themes/base/assets/css/theme.css b/nikola/data/themes/base/assets/css/theme.css index 18b93db..3cb8628 100644 --- a/nikola/data/themes/base/assets/css/theme.css +++ b/nikola/data/themes/base/assets/css/theme.css @@ -1,7 +1,7 @@ @charset "UTF-8"; /* - Copyright © 2014 Daniel Aleksandersen and others. + Copyright © 2014-2015 Daniel Aleksandersen and others. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -33,11 +33,6 @@ body { line-height: 1.4; padding: 1em; } -@media print { - body { - font-family: Garamond, serif; - } -} #container { margin: 1em auto; @@ -283,3 +278,111 @@ img { overflow: visible; clip: auto; } + +pre.code, code { + white-space: pre; + word-wrap: normal; + overflow: auto; +} + +/* SOURCE: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */ +@media print { + *, + *:before, + *:after { + background: transparent !important; + color: #000 !important; /* Black prints faster: http://www.sanbeiji.com/archives/953 */ + box-shadow: none !important; + text-shadow: none !important; + font-family: Garamond, Junicode, serif; + } + + body { + font-size: 12pt; + } + + a, + a:visited { + text-decoration: underline; + } + + a[href]:after { + content: " (" attr(href) ")"; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + /* + * Don't show links that are fragment identifiers, + * or use the `javascript:` pseudo protocol + */ + + a[href^="#"]:after, + a[href^="javascript:"]:after { + content: ""; + } + + pre, + blockquote { + border: 1px solid #999; + page-break-inside: avoid; + } + + /* + * Printing Tables: + * http://css-discuss.incutio.com/wiki/Printing_Tables + */ + + thead { + display: table-header-group; + } + + tr, + img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + + h2, + h3 { + page-break-after: avoid; + } + + .hidden-print { + display: none !important; + } + + article .entry-title a[href]:after, + article .metadata a[href]:after, + article .tags a[href]:after { + content: ""; + } + + article .metadata .sourceline { + display: none; + } + + article .metadata .linkline a[href]:after { + content: " (" attr(href) ")"; + } + + #header { + display: none; + } + + .postpromonav { + padding: 0; + } +} diff --git a/nikola/data/themes/base/assets/js/fancydates.js b/nikola/data/themes/base/assets/js/fancydates.js new file mode 100644 index 0000000..d13b11b --- /dev/null +++ b/nikola/data/themes/base/assets/js/fancydates.js @@ -0,0 +1,20 @@ +function fancydates(fanciness, date_format) { + if (fanciness == 0) { + return; + } + + dates = $('time.published.dt-published'); + + i = 0; + l = dates.length; + + for (i = 0; i < l; i++) { + d = moment(dates[i].attributes.datetime.value); + if (fanciness == 1) { + o = d.local().format(date_format); + } else { + o = d.fromNow(); + } + dates[i].innerHTML = o; + } +} diff --git a/nikola/data/themes/base/assets/js/mathjax.js b/nikola/data/themes/base/assets/js/mathjax.js index 5e14369..6ef2dd7 100644 --- a/nikola/data/themes/base/assets/js/mathjax.js +++ b/nikola/data/themes/base/assets/js/mathjax.js @@ -5,12 +5,7 @@ window.onload = function () { setTimeout(function () { var script = document.createElement("script"); - if (location.protocol == 'https:') { - scriptbase = "https://c328740.ssl.cf1.rackcdn.com/"; - } else { - scriptbase = "http://cdn.mathjax.org/"; - } - script.src = scriptbase + "mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"; + script.src = "https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"; document.getElementsByTagName("body")[0].appendChild(script); },1) } diff --git a/nikola/data/themes/base/assets/xml/atom.xsl b/nikola/data/themes/base/assets/xml/atom.xsl new file mode 100644 index 0000000..cc052e0 --- /dev/null +++ b/nikola/data/themes/base/assets/xml/atom.xsl @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.0"> +<xsl:output method="xml"/> +<xsl:template match="/"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> +<head> +<meta charset="UTF-8"/> +<meta name="viewport" content="width=device-width"/> +<title><xsl:value-of select="feed/title"/> (Atom feed)</title> +<style><![CDATA[html{margin:0;padding:0;}body{color:hsl(180,1%,31%);font-family:Helvetica,Arial,sans-serif;font-size:17px;line-height:1.4;margin:5%;max-width:35rem;padding:0;}input{min-width:20rem;margin-left:.2rem;padding-left:.2rem;padding-right:.2rem;}ol{list-style-type:disc;padding-left:1rem;}h2{font-size:22px;font-weight:inherit;}]]></style> +</head> +<body> +<h1><xsl:value-of select="feed/title"/> (Atom feed)</h1> +<p>This is an Atom feed. To subscribe to it, copy its address and paste it when your feed reader asks for it. It will be updated periodically in your reader. New to feeds? <a href="https://duckduckgo.com/?q=how+to+get+started+with+rss+feeds" title="Search on the web to learn more">Learn more</a>.</p> +<p> +<label for="address">Atom feed address:</label> +<input><xsl:attribute name="id">address</xsl:attribute><xsl:attribute name="spellcheck">false</xsl:attribute><xsl:attribute name="value"><xsl:value-of select="feed/link[@rel='self']/@href"/></xsl:attribute></input> +</p> +<p>Preview of the feed’s current headlines:</p> +<ol> +<xsl:for-each select="feed/entry"> +<li><h2><a><xsl:attribute name="href"><xsl:value-of select="link[@rel='alternate']/@href"/></xsl:attribute><xsl:value-of select="title"/></a></h2></li> +</xsl:for-each> +</ol> +</body> +</html> +</xsl:template> +</xsl:stylesheet> diff --git a/nikola/data/themes/base/assets/xml/rss.xsl b/nikola/data/themes/base/assets/xml/rss.xsl new file mode 100644 index 0000000..ee72301 --- /dev/null +++ b/nikola/data/themes/base/assets/xml/rss.xsl @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" version="1.0"> +<xsl:output method="xml"/> +<xsl:template match="/"> +<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> +<head> +<meta charset="UTF-8"/> +<meta name="viewport" content="width=device-width"/> +<title><xsl:value-of select="rss/channel/title"/> (RSS)</title> +<style><![CDATA[html{margin:0;padding:0;}body{color:hsl(180,1%,31%);font-family:Helvetica,Arial,sans-serif;font-size:17px;line-height:1.4;margin:5%;max-width:35rem;padding:0;}input{min-width:20rem;margin-left:.2rem;padding-left:.2rem;padding-right:.2rem;}ol{list-style-type:disc;padding-left:1rem;}h2{font-size:22px;font-weight:inherit;}]]></style> +</head> +<body> +<h1><xsl:value-of select="rss/channel/title"/> (RSS)</h1> +<p>This is an <abbr title="Really Simple Syndication">RSS</abbr> feed. To subscribe to it, copy its address and paste it when your feed reader asks for it. It will be updated periodically in your reader. New to feeds? <a href="https://duckduckgo.com/?q=how+to+get+started+with+rss+feeds" title="Search on the web to learn more">Learn more</a>.</p> +<p> +<label for="address">RSS address:</label> +<input><xsl:attribute name="id">address</xsl:attribute><xsl:attribute name="spellcheck">false</xsl:attribute><xsl:attribute name="value"><xsl:value-of select="rss/channel/atom:link[@rel='self']/@href"/></xsl:attribute></input> +</p> +<p>Preview of the feed’s current headlines:</p> +<ol> +<xsl:for-each select="rss/channel/item"> +<li><h2><a><xsl:attribute name="href"><xsl:value-of select="link"/></xsl:attribute><xsl:value-of select="title"/></a></h2></li> +</xsl:for-each> +</ol> +</body> +</html> +</xsl:template> +</xsl:stylesheet> diff --git a/nikola/data/themes/base/messages/messages_ar.py b/nikola/data/themes/base/messages/messages_ar.py index f7ba16a..07c38b2 100644 --- a/nikola/data/themes/base/messages/messages_ar.py +++ b/nikola/data/themes/base/messages/messages_ar.py @@ -3,32 +3,37 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "", - "Also available in:": "", - "Archive": "", - "Categories": "الأصناف", + "(active)": "", + "Also available in:": "أيضا متوفر في:", + "Archive": "الأرشيف", + "Categories": "فئات", "Comments": "التّعليقات", "LANGUAGE": "العربيّة", - "Languages:": "", + "Languages:": "اللغات", "More posts about %s": "المزيد من المقالات حول %s", - "Newer posts": "", - "Next post": "", - "No posts found.": "", - "Nothing found.": "", - "Older posts": "", - "Original site": "", - "Posted:": "", - "Posts about %s": "", - "Posts for year %s": "", + "Newer posts": "مقالات أحدث", + "Next post": "المقالة التالية", + "No posts found.": "لم يوجد مقالات.", + "Nothing found.": "لم يوجد شيء.", + "Older posts": "مقالات أقدم", + "Original site": "الموقع الأصلي", + "Posted:": "نشر:", + "Posts about %s": "مقالات عن s%", + "Posts for year %s": "مقالات سنة s%", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "", - "Previous post": "", - "Publication date": "", + "Previous post": "المقالة السابقة", + "Publication date": "تاريخ النشر", "RSS feed": "", - "Read in English": "", + "Read in English": "اقرأ بالعربية", "Read more": "قراءة المزيد", - "Skip to main content": "", - "Source": "", - "Tags and Categories": "", - "Tags": "", - "old posts, page %d": "", - "page %d": "", + "Skip to main content": "انتقل إلى المحتوى الرئيسي", + "Source": "المصدر", + "Subcategories:": "", + "Tags and Categories": "تصنيفات و فئات", + "Tags": "تصنيفات", + "Write your page here.": "", + "Write your post here.": "", + "old posts, page %d": "مقالات قديمة, صفحة d%", + "page %d": "صفحة d%", } diff --git a/nikola/data/themes/base/messages/messages_az.py b/nikola/data/themes/base/messages/messages_az.py new file mode 100644 index 0000000..76c15fc --- /dev/null +++ b/nikola/data/themes/base/messages/messages_az.py @@ -0,0 +1,39 @@ +# -*- encoding:utf-8 -*- +from __future__ import unicode_literals + +MESSAGES = { + "%d min remaining to read": "%d dəqiqəlik oxuma", + "(active)": "", + "Also available in:": "Həmçinin mövcuddur:", + "Archive": "Arxiv", + "Categories": "Kateqoriyalar", + "Comments": "Şərhlər", + "LANGUAGE": "Azərbaycan dili", + "Languages:": "Dillər:", + "More posts about %s": "%s ilə bağlı digər yazılar", + "Newer posts": "Yeni yazılar", + "Next post": "Növbəti yazı", + "No posts found.": "Heç bir yazı tapılmadı", + "Nothing found.": "Heç nə tapılmadı", + "Older posts": "Köhnə yazılar", + "Original site": "Original sayt", + "Posted:": "yazılma tarixi:", + "Posts about %s": "%s ilə bağlı yazılar", + "Posts for year %s": "%s ilindəki yazılar", + "Posts for {month} {day}, {year}": "{month} {day}, {year} üçün yazılar", + "Posts for {month} {year}": "{month} {year} üçün yazılar", + "Previous post": "Əvvəlki yazı", + "Publication date": "Buraxılış tarixi", + "RSS feed": "RSS", + "Read in English": "Azərbaycan dilində oxu", + "Read more": "Davamı", + "Skip to main content": "Əsas mövzuya keç", + "Source": "Mənbə", + "Subcategories:": "", + "Tags and Categories": "Teqlər və Kateqoriyalar", + "Tags": "Teqlər", + "Write your page here.": "", + "Write your post here.": "", + "old posts, page %d": "köhnə yazılar, səhifə %s", + "page %d": "səhifə %d", +} diff --git a/nikola/data/themes/base/messages/messages_bg.py b/nikola/data/themes/base/messages/messages_bg.py index 28adb77..96ac878 100644 --- a/nikola/data/themes/base/messages/messages_bg.py +++ b/nikola/data/themes/base/messages/messages_bg.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "", + "(active)": "", "Also available in:": "Също достъпно в:", "Archive": "Архив", "Categories": "Категории", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "Публиковано:", "Posts about %s": "Публикации относно %s", "Posts for year %s": "Публикации за %s година", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "Публикации за {month} {year}", "Previous post": "Предишна публикация", "Publication date": "", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "Прочети още", "Skip to main content": "", "Source": "Source", + "Subcategories:": "", "Tags and Categories": "Тагове и Категории", "Tags": "Тагове", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "стари публикации, страница %d", "page %d": "страница %d", } diff --git a/nikola/data/themes/base/messages/messages_ca.py b/nikola/data/themes/base/messages/messages_ca.py index 58c8577..f45b1a6 100644 --- a/nikola/data/themes/base/messages/messages_ca.py +++ b/nikola/data/themes/base/messages/messages_ca.py @@ -2,33 +2,38 @@ from __future__ import unicode_literals MESSAGES = { - "%d min remaining to read": "", + "%d min remaining to read": "% min recordar per a llegir", + "(active)": "", "Also available in:": "També disponibles en:", "Archive": "Arxiu", - "Categories": "", - "Comments": "", + "Categories": "Categories", + "Comments": "Comentaris", "LANGUAGE": "Català", - "Languages:": "", + "Languages:": "Llenguatges:", "More posts about %s": "Més entrades sobre %s", "Newer posts": "Entrades posteriors", "Next post": "Entrada següent", - "No posts found.": "", - "Nothing found.": "", + "No posts found.": "Publicació no trobada", + "Nothing found.": "No trobat", "Older posts": "Entrades anteriors", "Original site": "Lloc original", "Posted:": "Publicat:", "Posts about %s": "Entrades sobre %s", "Posts for year %s": "Entrades de l'any %s", - "Posts for {month} {year}": "", + "Posts for {month} {day}, {year}": "", + "Posts for {month} {year}": "Publicat en {month} {year}", "Previous post": "Entrada anterior", - "Publication date": "", - "RSS feed": "", + "Publication date": "Data de publicació", + "RSS feed": "Feed RSS", "Read in English": "Llegeix-ho en català", "Read more": "Llegeix-ne més", - "Skip to main content": "", + "Skip to main content": "Vés al comentari principal", "Source": "Codi", - "Tags and Categories": "", + "Subcategories:": "", + "Tags and Categories": "Etiquetes i Categories", "Tags": "Etiquetes", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "entrades antigues, pàgina %d", "page %d": "pàgina %d", } diff --git a/nikola/data/themes/base/messages/messages_cs.py b/nikola/data/themes/base/messages/messages_cs.py index 548c6d7..6e1bdd2 100644 --- a/nikola/data/themes/base/messages/messages_cs.py +++ b/nikola/data/themes/base/messages/messages_cs.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "%d min zbývajících", + "(active)": "", "Also available in:": "Dostupné také v", "Archive": "Archiv", "Categories": "Kategorie", @@ -19,16 +20,20 @@ MESSAGES = { "Posted:": "Zveřejněno:", "Posts about %s": "Příspěvky o %s", "Posts for year %s": "Příspěvky v roce %s", + "Posts for {month} {day}, {year}": "Příspěvky v {month} {day}, {year}", "Posts for {month} {year}": "Příspěvky v {month} {year}", "Previous post": "Předchozí příspěvek", "Publication date": "Datum zveřejnění", "RSS feed": "RSS zdroj", "Read in English": "Číst v češtině", "Read more": "Číst dál", - "Skip to main content": "", + "Skip to main content": "Přeskočit na hlavní obsah", "Source": "Zdroj", + "Subcategories:": "", "Tags and Categories": "Štítky a kategorie", "Tags": "Štítky", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "staré příspěvky, strana %d", "page %d": "strana %d", } diff --git a/nikola/data/themes/base/messages/messages_da.py b/nikola/data/themes/base/messages/messages_da.py index c5c82ee..73b71cb 100644 --- a/nikola/data/themes/base/messages/messages_da.py +++ b/nikola/data/themes/base/messages/messages_da.py @@ -2,33 +2,38 @@ from __future__ import unicode_literals MESSAGES = { - "%d min remaining to read": "", - "Also available in:": "", - "Archive": "", - "Categories": "", - "Comments": "", - "LANGUAGE": "", - "Languages:": "", - "More posts about %s": "", - "Newer posts": "", - "Next post": "", - "No posts found.": "", - "Nothing found.": "", - "Older posts": "", - "Original site": "", - "Posted:": "", - "Posts about %s": "", - "Posts for year %s": "", - "Posts for {month} {year}": "", - "Previous post": "", - "Publication date": "", - "RSS feed": "", - "Read in English": "", - "Read more": "", - "Skip to main content": "", - "Source": "", - "Tags and Categories": "", - "Tags": "", - "old posts, page %d": "", - "page %d": "", + "%d min remaining to read": "%d min. tilbage at læse", + "(active)": "", + "Also available in:": "Fås også i:", + "Archive": "Arkiv", + "Categories": "Kategorier", + "Comments": "Kommentarer", + "LANGUAGE": "Dansk", + "Languages:": "Sprog:", + "More posts about %s": "Yderligere indlæg om %s", + "Newer posts": "Nyere indlæg", + "Next post": "Næste indlæg", + "No posts found.": "Søgningen gav ingen resultater.", + "Nothing found.": "Søgningen gav ingen resultater.", + "Older posts": "Ældre indlæg", + "Original site": "Oprindeligt hjemmeside", + "Posted:": "Opslået:", + "Posts about %s": "Indlæg om %s", + "Posts for year %s": "Indlæg for %s", + "Posts for {month} {day}, {year}": "Indlæs for {month} {day}, {year}", + "Posts for {month} {year}": "Indlæg for {month} {year}", + "Previous post": "Tidligere indlæg", + "Publication date": "Udgivelsesdato", + "RSS feed": "RSS-nyhedskilde", + "Read in English": "Læs på dansk", + "Read more": "Læs mere", + "Skip to main content": "Hop direkte til hovedindhold", + "Source": "Kilde", + "Subcategories:": "", + "Tags and Categories": "Nøgleord og kategorier", + "Tags": "Nøgleord", + "Write your page here.": "", + "Write your post here.": "", + "old posts, page %d": "gamle indlæg, side %d", + "page %d": "side %d", } diff --git a/nikola/data/themes/base/messages/messages_de.py b/nikola/data/themes/base/messages/messages_de.py index 6be6ad5..324dd14 100644 --- a/nikola/data/themes/base/messages/messages_de.py +++ b/nikola/data/themes/base/messages/messages_de.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "%d min verbleiben zum Lesen", + "(active)": "", "Also available in:": "Auch verfügbar in:", "Archive": "Archiv", "Categories": "Kategorien", @@ -19,16 +20,20 @@ MESSAGES = { "Posted:": "Veröffentlicht:", "Posts about %s": "Einträge über %s", "Posts for year %s": "Einträge aus dem Jahr %s", + "Posts for {month} {day}, {year}": "Einträge vom {day}. {month} {year}", "Posts for {month} {year}": "Einträge aus {month} {year}", "Previous post": "Vorheriger Eintrag", "Publication date": "Veröffentlichungsdatum", "RSS feed": "RSS-Feed", "Read in English": "Auf Deutsch lesen", "Read more": "Weiterlesen", - "Skip to main content": "", + "Skip to main content": "Springe zum Hauptinhalt", "Source": "Source", + "Subcategories:": "Unterkategorien:", "Tags and Categories": "Tags und Kategorien", "Tags": "Tags", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "Ältere Einträge, Seite %d", "page %d": "Seite %d", } diff --git a/nikola/data/themes/base/messages/messages_el.py b/nikola/data/themes/base/messages/messages_el.py index ce2fd89..68cf91f 100644 --- a/nikola/data/themes/base/messages/messages_el.py +++ b/nikola/data/themes/base/messages/messages_el.py @@ -3,32 +3,37 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "", + "(active)": "", "Also available in:": "Διαθέσιμο και στα:", "Archive": "Αρχείο", "Categories": "Κατηγορίες", - "Comments": "", + "Comments": "Σχόλια", "LANGUAGE": "Ελληνικά", - "Languages:": "", + "Languages:": "Γλώσσες", "More posts about %s": "Περισσότερες αναρτήσεις για %s", "Newer posts": "Νεότερες αναρτήσεις", "Next post": "Επόμενη ανάρτηση", - "No posts found.": "", - "Nothing found.": "", + "No posts found.": "Δε βρέθηκαν αναρτήσεις", + "Nothing found.": "Δε βρέθηκε περιεχόμενο", "Older posts": "Παλαιότερες αναρτήσεις", "Original site": "Ιστοσελίδα αρχικής ανάρτησης", "Posted:": "Αναρτήθηκε:", "Posts about %s": "Αναρτήσεις για %s", "Posts for year %s": "Αναρτήσεις για το έτος %s", + "Posts for {month} {day}, {year}": "Αναρτήσεις στις {day} {month}, {year}", "Posts for {month} {year}": "Αναρτήσεις για τον {month} του {year}", "Previous post": "Προηγούμενη ανάρτηση", - "Publication date": "", + "Publication date": "Ημερομηνία δημοσίευσης", "RSS feed": "", "Read in English": "Διαβάστε στα Ελληνικά", "Read more": "Διαβάστε περισσότερα", "Skip to main content": "", "Source": "Πηγαίος κώδικας", + "Subcategories:": "", "Tags and Categories": "Ετικέτες και κατηγορίες", "Tags": "Ετικέτες", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "σελίδα παλαιότερων αναρτήσεων %d", "page %d": "σελίδα %d", } diff --git a/nikola/data/themes/base/messages/messages_en.py b/nikola/data/themes/base/messages/messages_en.py index df04974..29af257 100644 --- a/nikola/data/themes/base/messages/messages_en.py +++ b/nikola/data/themes/base/messages/messages_en.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "%d min remaining to read", + "(active)": "(active)", "Also available in:": "Also available in:", "Archive": "Archive", "Categories": "Categories", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "Posted:", "Posts about %s": "Posts about %s", "Posts for year %s": "Posts for year %s", + "Posts for {month} {day}, {year}": "Posts for {month} {day}, {year}", "Posts for {month} {year}": "Posts for {month} {year}", "Previous post": "Previous post", "Publication date": "Publication date", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "Read more", "Skip to main content": "Skip to main content", "Source": "Source", + "Subcategories:": "Subcategories:", "Tags and Categories": "Tags and Categories", "Tags": "Tags", + "Write your page here.": "Write your page here.", + "Write your post here.": "Write your post here.", "old posts, page %d": "old posts, page %d", "page %d": "page %d", } diff --git a/nikola/data/themes/base/messages/messages_eo.py b/nikola/data/themes/base/messages/messages_eo.py index 38b54e2..8938707 100644 --- a/nikola/data/themes/base/messages/messages_eo.py +++ b/nikola/data/themes/base/messages/messages_eo.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "", + "(active)": "", "Also available in:": "Ankaŭ disponebla en:", "Archive": "Arĥivo", "Categories": "Kategorioj", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "Skribita:", "Posts about %s": "Artikoloj pri %s", "Posts for year %s": "Artikoloj de la jaro %s", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "Artikoloj skribitaj en {month} {year}", "Previous post": "Antaŭa artikolo", "Publication date": "", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "Legu plu", "Skip to main content": "", "Source": "Fonto", + "Subcategories:": "", "Tags and Categories": "Etikedoj kaj Kategorioj", "Tags": "Etikedoj", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "paĝo de malnovaj artikoloj %d", "page %d": "paĝo %d", } diff --git a/nikola/data/themes/base/messages/messages_es.py b/nikola/data/themes/base/messages/messages_es.py index 67de5aa..e3f0f03 100644 --- a/nikola/data/themes/base/messages/messages_es.py +++ b/nikola/data/themes/base/messages/messages_es.py @@ -2,33 +2,38 @@ from __future__ import unicode_literals MESSAGES = { - "%d min remaining to read": "restan %d minutos", + "%d min remaining to read": "quedan %d minutos de lectura", + "(active)": "(activo)", "Also available in:": "También disponible en:", "Archive": "Archivo", "Categories": "Categorías", "Comments": "Comentarios", "LANGUAGE": "Español", "Languages:": "Idiomas:", - "More posts about %s": "Más posts sobre %s", - "Newer posts": "Posts posteriores", - "Next post": "Siguiente post", - "No posts found.": "No se encontraron posts", - "Nothing found.": "No encontrado", - "Older posts": "Posts anteriores", + "More posts about %s": "Más publicaciones sobre %s", + "Newer posts": "Publicaciones posteriores", + "Next post": "Siguiente publicación", + "No posts found.": "No se encontraron publicaciones.", + "Nothing found.": "No se encontró nada.", + "Older posts": "Publicaciones anteriores", "Original site": "Sitio original", "Posted:": "Publicado:", - "Posts about %s": "Posts sobre %s", - "Posts for year %s": "Posts del año %s", + "Posts about %s": "Publicaciones sobre %s", + "Posts for year %s": "Publicaciones del año %s", + "Posts for {month} {day}, {year}": "Publicaciones de {day}, {month}, {year}", "Posts for {month} {year}": "Posts de {month} {year}", - "Previous post": "Post anterior", + "Previous post": "Publicación anterior", "Publication date": "Fecha de publicación", - "RSS feed": "feed RSS", + "RSS feed": "Canal RSS", "Read in English": "Leer en español", "Read more": "Leer más", - "Skip to main content": "", - "Source": "Código", - "Tags and Categories": "Tags y Categorías", - "Tags": "Tags", - "old posts, page %d": "posts antiguos, página %d", + "Skip to main content": "Ir al contenido principal", + "Source": "Código fuente", + "Subcategories:": "Subcategorías:", + "Tags and Categories": "Etiquetas y Categorías", + "Tags": "Etiquetas", + "Write your page here.": "", + "Write your post here.": "", + "old posts, page %d": "publicaciones antiguas, página %d", "page %d": "página %d", } diff --git a/nikola/data/themes/base/messages/messages_et.py b/nikola/data/themes/base/messages/messages_et.py index 3a53c2f..c67cbb2 100644 --- a/nikola/data/themes/base/messages/messages_et.py +++ b/nikola/data/themes/base/messages/messages_et.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "", + "(active)": "", "Also available in:": "Saadaval ka:", "Archive": "Arhiiv", "Categories": "Kategooriad", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "Postitatud:", "Posts about %s": "Postitused %s kohta", "Posts for year %s": "Postitused aastast %s", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "Postitused {year} aasta kuust {month} ", "Previous post": "Eelmine postitus", "Publication date": "", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "Loe veel", "Skip to main content": "", "Source": "Lähtekood", + "Subcategories:": "", "Tags and Categories": "Sildid ja kategooriad", "Tags": "Märksõnad", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "vanade postituste, leht %d", "page %d": "leht %d", } diff --git a/nikola/data/themes/base/messages/messages_eu.py b/nikola/data/themes/base/messages/messages_eu.py index 6920552..1588cd6 100644 --- a/nikola/data/themes/base/messages/messages_eu.py +++ b/nikola/data/themes/base/messages/messages_eu.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "", + "(active)": "", "Also available in:": "Eskuragarria hemen ere:", "Archive": "Artxiboa", "Categories": "Kategoriak", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "Argitaratuta:", "Posts about %s": "%s-ri buruzko postak", "Posts for year %s": "%s. urteko postak", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "{year}ko {month}ren postak", "Previous post": "Aurreko posta", "Publication date": "", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "Irakurri gehiago", "Skip to main content": "", "Source": "Iturria", + "Subcategories:": "", "Tags and Categories": "Etiketak eta Kategoriak", "Tags": "Etiketak", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "Post zaharren, orria %d", "page %d": "orria %d", } diff --git a/nikola/data/themes/base/messages/messages_fa.py b/nikola/data/themes/base/messages/messages_fa.py index 5899ec5..b69d57a 100644 --- a/nikola/data/themes/base/messages/messages_fa.py +++ b/nikola/data/themes/base/messages/messages_fa.py @@ -2,7 +2,8 @@ from __future__ import unicode_literals MESSAGES = { - "%d min remaining to read": "", + "%d min remaining to read": "%d دقیقه برای خواندن باقی مانده", + "(active)": "", "Also available in:": "همچنین قابل دسترس از:", "Archive": "آرشیو", "Categories": "دستهها", @@ -19,16 +20,20 @@ MESSAGES = { "Posted:": "ارسال شده:", "Posts about %s": "ارسالها دربارهٔ %s", "Posts for year %s": "ارسالها برای سال %s", + "Posts for {month} {day}, {year}": "ارسال برای {month} {day}. {year}", "Posts for {month} {year}": "ارسال برای {month} {year}", "Previous post": "ارسال پیشین", "Publication date": "تاریخ انتشار", "RSS feed": "خوراک", "Read in English": "به فارسی بخوانید", "Read more": "بیشتر بخوانید", - "Skip to main content": "", + "Skip to main content": "متن اصلی را نادیده بگیر", "Source": "منبع", + "Subcategories:": "", "Tags and Categories": "برچسبها و دستهها", "Tags": "برچسبها", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "صفحهٔ ارسالهای قدیمی %d", "page %d": "برگه %d", } diff --git a/nikola/data/themes/base/messages/messages_fi.py b/nikola/data/themes/base/messages/messages_fi.py index 1988e3f..bcc2680 100644 --- a/nikola/data/themes/base/messages/messages_fi.py +++ b/nikola/data/themes/base/messages/messages_fi.py @@ -2,7 +2,8 @@ from __future__ import unicode_literals MESSAGES = { - "%d min remaining to read": "", + "%d min remaining to read": "%d minuuttia lukuaikaa", + "(active)": "", "Also available in:": "Saatavilla myös:", "Archive": "Arkisto", "Categories": "Kategoriat", @@ -19,16 +20,20 @@ MESSAGES = { "Posted:": "Postattu:", "Posts about %s": "Postauksia aiheesta %s", "Posts for year %s": "Postauksia vuodelta %s", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "Postauksia ajalle {month} {year}", "Previous post": "Vanhempia postauksia", "Publication date": "Julkaisupäivämäärä", "RSS feed": "RSS syöte", "Read in English": "Lue suomeksi", "Read more": "Lue lisää", - "Skip to main content": "", + "Skip to main content": "Hyppää sisältöön", "Source": "Lähde", + "Subcategories:": "", "Tags and Categories": "Tagit ja kategoriat", "Tags": "Tagit", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "vanhoja postauksia, sivu %d", "page %d": "sivu %d", } diff --git a/nikola/data/themes/base/messages/messages_fil.py b/nikola/data/themes/base/messages/messages_fil.py new file mode 100644 index 0000000..fd26d77 --- /dev/null +++ b/nikola/data/themes/base/messages/messages_fil.py @@ -0,0 +1,39 @@ +# -*- encoding:utf-8 -*- +from __future__ import unicode_literals + +MESSAGES = { + "%d min remaining to read": "", + "(active)": "", + "Also available in:": "", + "Archive": "", + "Categories": "", + "Comments": "", + "LANGUAGE": "", + "Languages:": "", + "More posts about %s": "", + "Newer posts": "", + "Next post": "", + "No posts found.": "", + "Nothing found.": "", + "Older posts": "", + "Original site": "", + "Posted:": "", + "Posts about %s": "", + "Posts for year %s": "", + "Posts for {month} {day}, {year}": "", + "Posts for {month} {year}": "", + "Previous post": "", + "Publication date": "", + "RSS feed": "", + "Read in English": "", + "Read more": "", + "Skip to main content": "", + "Source": "", + "Subcategories:": "", + "Tags and Categories": "", + "Tags": "", + "Write your page here.": "", + "Write your post here.": "", + "old posts, page %d": "", + "page %d": "", +} diff --git a/nikola/data/themes/base/messages/messages_fr.py b/nikola/data/themes/base/messages/messages_fr.py index a30aa1a..327b3f7 100644 --- a/nikola/data/themes/base/messages/messages_fr.py +++ b/nikola/data/themes/base/messages/messages_fr.py @@ -3,22 +3,24 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "Il reste encore %d min. de lecture", - "Also available in:": "Egalement disponible en:", + "(active)": "(actif)", + "Also available in:": "Également disponible en:", "Archive": "Archives", "Categories": "Catégories", "Comments": "Commentaires", "LANGUAGE": "Français", "Languages:": "Langues:", "More posts about %s": "Plus d'articles sur %s", - "Newer posts": "Billets récents", + "Newer posts": "Articles récents", "Next post": "Article suivant", - "No posts found.": "Pas de billets.", + "No posts found.": "Pas d'articles.", "Nothing found.": "Pas de résultats.", "Older posts": "Anciens articles", "Original site": "Site d'origine", "Posted:": "Publié:", "Posts about %s": "Articles sur %s", "Posts for year %s": "Articles de l'année %s", + "Posts for {month} {day}, {year}": "Articles du {day} {month} {year}", "Posts for {month} {year}": "Articles de {month} {year}", "Previous post": "Article précédent", "Publication date": "Date de publication", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "Lire la suite", "Skip to main content": "Aller au contenu principal", "Source": "Source", + "Subcategories:": "Sous-catégories", "Tags and Categories": "Étiquettes et catégories", "Tags": "Étiquettes", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "anciens articles, page %d", "page %d": "page %d", } diff --git a/nikola/data/themes/base/messages/messages_gl.py b/nikola/data/themes/base/messages/messages_gl.py index c5c82ee..fd26d77 100644 --- a/nikola/data/themes/base/messages/messages_gl.py +++ b/nikola/data/themes/base/messages/messages_gl.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "", + "(active)": "", "Also available in:": "", "Archive": "", "Categories": "", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "", "Posts about %s": "", "Posts for year %s": "", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "", "Previous post": "", "Publication date": "", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "", "Skip to main content": "", "Source": "", + "Subcategories:": "", "Tags and Categories": "", "Tags": "", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "", "page %d": "", } diff --git a/nikola/data/themes/base/messages/messages_hi.py b/nikola/data/themes/base/messages/messages_hi.py index 3d69697..7804b60 100644 --- a/nikola/data/themes/base/messages/messages_hi.py +++ b/nikola/data/themes/base/messages/messages_hi.py @@ -2,33 +2,38 @@ from __future__ import unicode_literals MESSAGES = { - "%d min remaining to read": "", + "%d min remaining to read": "पढ़ने में %d मिनट बाकी", + "(active)": "", "Also available in:": "उपलब्ध भाषाएँ:", "Archive": "आर्काइव", "Categories": "श्रेणियाँ", - "Comments": "", + "Comments": "टिप्पणियाँ", "LANGUAGE": "हिन्दी", - "Languages:": "", + "Languages:": "भाषाएँ:", "More posts about %s": "%s के बारे में अौर पोस्टें", "Newer posts": "नई पोस्टें", "Next post": "अगली पोस्ट", - "No posts found.": "", - "Nothing found.": "", + "No posts found.": "कोई पोस्ट नहीं मिल सकी", + "Nothing found.": "कुछ नहीं मिल सका", "Older posts": "पुरानी पोस्टें", "Original site": "असली साइट", "Posted:": "पोस्टेड:", "Posts about %s": "%s के बारे में पोस्टें", "Posts for year %s": "साल %s की पोस्टें", + "Posts for {month} {day}, {year}": "{day} {month} {year} की पोस्टें", "Posts for {month} {year}": "{month} {year} की पोस्टें", "Previous post": "पिछली पोस्ट", - "Publication date": "", - "RSS feed": "", + "Publication date": "प्रकाशन की तारीख", + "RSS feed": "आर एस एस फ़ीड", "Read in English": "हिन्दी में पढ़िए", "Read more": "और पढ़िए", - "Skip to main content": "", + "Skip to main content": "मुख्य सामग्री पर जाएँ", "Source": "सोर्स", + "Subcategories:": "", "Tags and Categories": "टैग्स और श्रेणियाँ", "Tags": "टैग्स", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "पुरानी पोस्टें, पृष्ठ %d", "page %d": "पृष्ठ %d", } diff --git a/nikola/data/themes/base/messages/messages_hr.py b/nikola/data/themes/base/messages/messages_hr.py index f5f0886..d26fc85 100644 --- a/nikola/data/themes/base/messages/messages_hr.py +++ b/nikola/data/themes/base/messages/messages_hr.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "", + "(active)": "", "Also available in:": "Također dostupno i u:", "Archive": "Arhiva", "Categories": "Kategorije", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "Objavljeno:", "Posts about %s": "Postovi o %s", "Posts for year %s": "Postovi za godinu %s", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "Postovi za {month} {year}", "Previous post": "Prethodni post", "Publication date": "Nadnevak objave", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "Čitaj dalje", "Skip to main content": "", "Source": "Izvor", + "Subcategories:": "", "Tags and Categories": "Tagovi i kategorije", "Tags": "Tagovi", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "stari postovi, stranice %d", "page %d": "stranice %d", } diff --git a/nikola/data/themes/base/messages/messages_id.py b/nikola/data/themes/base/messages/messages_id.py new file mode 100644 index 0000000..475299f --- /dev/null +++ b/nikola/data/themes/base/messages/messages_id.py @@ -0,0 +1,39 @@ +# -*- encoding:utf-8 -*- +from __future__ import unicode_literals + +MESSAGES = { + "%d min remaining to read": "%d menit tersisa untuk membaca", + "(active)": "(aktif)", + "Also available in:": "Juga tersedia dalam:", + "Archive": "Arsip", + "Categories": "Kategori", + "Comments": "Komentar", + "LANGUAGE": "Inggris", + "Languages:": "Bahasa:", + "More posts about %s": "Lebih banyak tulisan tentang %s", + "Newer posts": "Tulisan lebih baru", + "Next post": "Tulisan berikutnya", + "No posts found.": "Tidak ada tulisan yang ditemukan.", + "Nothing found.": "Tidak ditemukan.", + "Older posts": "Tulisan lebih lama", + "Original site": "Situs orisinal", + "Posted:": "Ditulis oleh:", + "Posts about %s": "Tulisan tentang %s", + "Posts for year %s": "Tulisan untuk tahun %s", + "Posts for {month} {day}, {year}": "Tulisan untuk {month} {day}, {year}", + "Posts for {month} {year}": "Tulisan untuk {month} {year}", + "Previous post": "Tulisan sebelumnya", + "Publication date": "Tanggal publikasi", + "RSS feed": "Sindikasi RSS", + "Read in English": "Baca dalam bahasa Inggris", + "Read more": "Baca selengkapnya", + "Skip to main content": "Lanjutkan ke konten utama", + "Source": "Sumber", + "Subcategories:": "Sub kategori:", + "Tags and Categories": "Tag dan Kategori", + "Tags": "Tag", + "Write your page here.": "", + "Write your post here.": "", + "old posts, page %d": "tulisan lama, halaman %d", + "page %d": "halaman %d", +} diff --git a/nikola/data/themes/base/messages/messages_it.py b/nikola/data/themes/base/messages/messages_it.py index 62442d4..91f8374 100644 --- a/nikola/data/themes/base/messages/messages_it.py +++ b/nikola/data/themes/base/messages/messages_it.py @@ -2,15 +2,16 @@ from __future__ import unicode_literals MESSAGES = { - "%d min remaining to read": "ancora %d minuti", - "Also available in:": "Anche disponibile in:", + "%d min remaining to read": "ulteriori %d minuti di lettura", + "(active)": "(attivo)", + "Also available in:": "Disponibile anche in:", "Archive": "Archivio", "Categories": "Categorie", "Comments": "Commenti", - "LANGUAGE": "Italiano", + "LANGUAGE": "Inglese", "Languages:": "Lingue:", "More posts about %s": "Altri articoli collegati %s", - "Newer posts": "Articoli recenti", + "Newer posts": "Articoli più recenti", "Next post": "Articolo successivo", "No posts found.": "Nessun articolo trovato.", "Nothing found.": "Non trovato.", @@ -19,16 +20,20 @@ MESSAGES = { "Posted:": "Pubblicato:", "Posts about %s": "Articoli su %s", "Posts for year %s": "Articoli per l'anno %s", + "Posts for {month} {day}, {year}": "Articoli per il {day} {month} {year}", "Posts for {month} {year}": "Articoli per {month} {year}", "Previous post": "Articolo precedente", "Publication date": "Data di pubblicazione", - "RSS feed": "Flusso RSS", - "Read in English": "Leggi in italiano", + "RSS feed": "Feed RSS", + "Read in English": "Leggi in inglese", "Read more": "Continua la lettura", - "Skip to main content": "", + "Skip to main content": "Vai al testo principale", "Source": "Sorgente", - "Tags and Categories": "Tags e Categorie", - "Tags": "Tags", - "old posts, page %d": "pagina dei vecchi articoli %d", + "Subcategories:": "Sottocategorie:", + "Tags and Categories": "Tag e Categorie", + "Tags": "Tag", + "Write your page here.": "Scrivi qui la tua pagina.", + "Write your post here.": "Scrivi qui il tuo post.", + "old posts, page %d": "vecchi articoli, pagina %d", "page %d": "pagina %d", } diff --git a/nikola/data/themes/base/messages/messages_ja.py b/nikola/data/themes/base/messages/messages_ja.py index cba5ee9..972794d 100644 --- a/nikola/data/themes/base/messages/messages_ja.py +++ b/nikola/data/themes/base/messages/messages_ja.py @@ -2,7 +2,8 @@ from __future__ import unicode_literals MESSAGES = { - "%d min remaining to read": "", + "%d min remaining to read": "読込むまで残り %d 分", + "(active)": "", "Also available in:": "他の言語で読む:", "Archive": "過去の記事", "Categories": "カテゴリー", @@ -19,16 +20,20 @@ MESSAGES = { "Posted:": "投稿日時:", "Posts about %s": "%sについての記事", "Posts for year %s": "%s年の記事", + "Posts for {month} {day}, {year}": "{year}年{month}月{day}日の記事", "Posts for {month} {year}": "{year}年{month}月の記事", "Previous post": "前の記事", "Publication date": "投稿日", "RSS feed": "RSS フィード", "Read in English": "日本語で読む", "Read more": "続きを読む", - "Skip to main content": "", + "Skip to main content": "メインコンテンツをスキップ", "Source": "ソース", + "Subcategories:": "", "Tags and Categories": "タグとカテゴリー", "Tags": "タグ", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "前の記事 %dページ目", "page %d": "ページ %d", } diff --git a/nikola/data/themes/base/messages/messages_ko.py b/nikola/data/themes/base/messages/messages_ko.py new file mode 100644 index 0000000..6904492 --- /dev/null +++ b/nikola/data/themes/base/messages/messages_ko.py @@ -0,0 +1,39 @@ +# -*- encoding:utf-8 -*- +from __future__ import unicode_literals + +MESSAGES = { + "%d min remaining to read": "읽기 %d분 남음.", + "(active)": "", + "Also available in:": "", + "Archive": "저장소", + "Categories": "분류", + "Comments": "댓글", + "LANGUAGE": "영어", + "Languages:": "언어:", + "More posts about %s": "%s에 대한 또다른 포스트", + "Newer posts": "최신 포스트", + "Next post": "다음 포스트", + "No posts found.": "검색된 포스트 없음.", + "Nothing found.": "검색 결과 없음.", + "Older posts": "옛날 포스트", + "Original site": "출처", + "Posted:": "", + "Posts about %s": "%s에 대한 포스트", + "Posts for year %s": "%s년도 포스트", + "Posts for {month} {day}, {year}": "", + "Posts for {month} {year}": "{year}년 {month}월에 쓴 포스트", + "Previous post": "이전 포스트", + "Publication date": "발간일", + "RSS feed": "RSS 목록", + "Read in English": "영어로 읽기", + "Read more": "더 읽기", + "Skip to main content": "주 콘텐츠로 바로가기", + "Source": "원문", + "Subcategories:": "", + "Tags and Categories": "태그와 분류", + "Tags": "태그", + "Write your page here.": "", + "Write your post here.": "", + "old posts, page %d": "이전 포스트, 페이지 %d", + "page %d": "페이지 %d", +} diff --git a/nikola/data/themes/base/messages/messages_nb.py b/nikola/data/themes/base/messages/messages_nb.py index f4d6062..2533247 100644 --- a/nikola/data/themes/base/messages/messages_nb.py +++ b/nikola/data/themes/base/messages/messages_nb.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "", + "(active)": "", "Also available in:": "Også tilgjengelig på:", "Archive": "Arkiv", "Categories": "Kategorier", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "Publisert:", "Posts about %s": "Innlegg om %s", "Posts for year %s": "Innlegg fra %s", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "Innlegg fra {month} {year}", "Previous post": "Forrige innlegg", "Publication date": "", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "Les mer", "Skip to main content": "", "Source": "Kilde", + "Subcategories:": "", "Tags and Categories": "Merker og kategorier", "Tags": "Merker", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "eldre innlegg, side %d", "page %d": "side %d", } diff --git a/nikola/data/themes/base/messages/messages_nl.py b/nikola/data/themes/base/messages/messages_nl.py index 4aa9147..0661ce1 100644 --- a/nikola/data/themes/base/messages/messages_nl.py +++ b/nikola/data/themes/base/messages/messages_nl.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "%d min resterende leestijd ", + "(active)": "(actief)", "Also available in:": "Ook beschikbaar in:", "Archive": "Archief", "Categories": "Categorieën", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "Geplaatst:", "Posts about %s": "Berichten over %s", "Posts for year %s": "Berichten voor het jaar %s", + "Posts for {month} {day}, {year}": "Berichten voor {month} {day}, {year}", "Posts for {month} {year}": "Berichten voor {month} {year}", "Previous post": "Vorig bericht", "Publication date": "Publicatiedatum", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "Lees verder", "Skip to main content": "Ga door naar de hoofdinhoud", "Source": "Bron", + "Subcategories:": "Subcategorieën", "Tags and Categories": "Tags en Categorieën", "Tags": "Tags", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "oude berichten, pagina %d", "page %d": "pagina %d", } diff --git a/nikola/data/themes/base/messages/messages_pl.py b/nikola/data/themes/base/messages/messages_pl.py index b1d4e82..89aae0f 100644 --- a/nikola/data/themes/base/messages/messages_pl.py +++ b/nikola/data/themes/base/messages/messages_pl.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "zostało %d minut czytania", + "(active)": "(aktywne)", "Also available in:": "Również dostępny w językach:", "Archive": "Archiwum", "Categories": "Kategorie", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "Opublikowano:", "Posts about %s": "Posty o %s", "Posts for year %s": "Posty z roku %s", + "Posts for {month} {day}, {year}": "Posty z {day} {month} {year}", "Posts for {month} {year}": "Posty z {month} {year}", "Previous post": "Poprzedni post", "Publication date": "Data publikacji", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "Czytaj więcej", "Skip to main content": "Przejdź do treści", "Source": "Źródło", + "Subcategories:": "Podkategorie:", "Tags and Categories": "Tagi i Kategorie", "Tags": "Tagi", + "Write your page here.": "Tu wpisz treść strony.", + "Write your post here.": "Tu wpisz treść postu.", "old posts, page %d": "stare posty, strona %d", "page %d": "strona %d", } diff --git a/nikola/data/themes/base/messages/messages_pt.py b/nikola/data/themes/base/messages/messages_pt.py index c5c82ee..fd26d77 100644 --- a/nikola/data/themes/base/messages/messages_pt.py +++ b/nikola/data/themes/base/messages/messages_pt.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "", + "(active)": "", "Also available in:": "", "Archive": "", "Categories": "", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "", "Posts about %s": "", "Posts for year %s": "", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "", "Previous post": "", "Publication date": "", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "", "Skip to main content": "", "Source": "", + "Subcategories:": "", "Tags and Categories": "", "Tags": "", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "", "page %d": "", } diff --git a/nikola/data/themes/base/messages/messages_pt_br.py b/nikola/data/themes/base/messages/messages_pt_br.py index 0805f8e..58ad63f 100644 --- a/nikola/data/themes/base/messages/messages_pt_br.py +++ b/nikola/data/themes/base/messages/messages_pt_br.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "%d mín restante para leitura", + "(active)": "", "Also available in:": "Também disponível em:", "Archive": "Arquivo", "Categories": "Categorias", @@ -19,16 +20,20 @@ MESSAGES = { "Posted:": "Publicado:", "Posts about %s": "Posts sobre %s", "Posts for year %s": "Posts do ano %s", + "Posts for {month} {day}, {year}": "Posts do {day} {month}, {year}", "Posts for {month} {year}": "Posts de {month} {year}", "Previous post": "Post anterior", "Publication date": "Data de publicação", "RSS feed": "Feed RSS", "Read in English": "Ler em português", "Read more": "Leia mais", - "Skip to main content": "", + "Skip to main content": "Pular para o conteúdo principal", "Source": "Código", + "Subcategories:": "", "Tags and Categories": "Tags e Categorias", "Tags": "Tags", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "Posts antigos, página %d", "page %d": "página %d", } diff --git a/nikola/data/themes/base/messages/messages_ru.py b/nikola/data/themes/base/messages/messages_ru.py index 7205906..cfbe536 100644 --- a/nikola/data/themes/base/messages/messages_ru.py +++ b/nikola/data/themes/base/messages/messages_ru.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "%d минут чтения осталось", + "(active)": "", "Also available in:": "Также доступно на:", "Archive": "Архив", "Categories": "Категории", @@ -19,16 +20,20 @@ MESSAGES = { "Posted:": "Опубликовано:", "Posts about %s": "Записи о %s", "Posts for year %s": "Записи за %s год", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "Записи за {month} {year}", "Previous post": "Предыдущая запись", "Publication date": "Дата опубликования", "RSS feed": "RSS лента", "Read in English": "Прочесть по-русски", "Read more": "Читать далее", - "Skip to main content": "", + "Skip to main content": "Перейти к главному содержимому", "Source": "Источник", + "Subcategories:": "", "Tags and Categories": "Тэги и категории", "Tags": "Тэги", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "%d страница со старыми записями", "page %d": "%d страница", } diff --git a/nikola/data/themes/base/messages/messages_si_lk.py b/nikola/data/themes/base/messages/messages_si_lk.py index c5c82ee..fd26d77 100644 --- a/nikola/data/themes/base/messages/messages_si_lk.py +++ b/nikola/data/themes/base/messages/messages_si_lk.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "", + "(active)": "", "Also available in:": "", "Archive": "", "Categories": "", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "", "Posts about %s": "", "Posts for year %s": "", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "", "Previous post": "", "Publication date": "", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "", "Skip to main content": "", "Source": "", + "Subcategories:": "", "Tags and Categories": "", "Tags": "", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "", "page %d": "", } diff --git a/nikola/data/themes/base/messages/messages_sk.py b/nikola/data/themes/base/messages/messages_sk.py index e3618f3..a793ba6 100644 --- a/nikola/data/themes/base/messages/messages_sk.py +++ b/nikola/data/themes/base/messages/messages_sk.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "zostáva %d minút na čítanie", + "(active)": "", "Also available in:": "Tiež dostupné v:", "Archive": "Archív", "Categories": "Kategórie", @@ -19,16 +20,20 @@ MESSAGES = { "Posted:": "Zverejnené:", "Posts about %s": "Príspevky o %s", "Posts for year %s": "Príspevky z roku %s", + "Posts for {month} {day}, {year}": "Príspevky z dňa {day}. {month} {year}", "Posts for {month} {year}": "Príspevky za mesiac {month} z roku {year}", "Previous post": "Predchádzajúci príspevok", "Publication date": "Dátum zverejnenia", "RSS feed": "RSS kanál", "Read in English": "Čítať v slovenčine", "Read more": "Čítať ďalej", - "Skip to main content": "", + "Skip to main content": "Skočiť na hlavný obsah", "Source": "Zdroj", + "Subcategories:": "", "Tags and Categories": "Štítky a kategórie", "Tags": "Štítky", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "staré príspevky, strana %d", "page %d": "stránka %d", } diff --git a/nikola/data/themes/base/messages/messages_sl.py b/nikola/data/themes/base/messages/messages_sl.py index f9f1d13..992787b 100644 --- a/nikola/data/themes/base/messages/messages_sl.py +++ b/nikola/data/themes/base/messages/messages_sl.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "še %d min za branje preostanka", + "(active)": "", "Also available in:": "Na voljo tudi v:", "Archive": "Arhiv", "Categories": "Kategorije", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "Objavljeno:", "Posts about %s": "Objave o %s", "Posts for year %s": "Objave za leto %s", + "Posts for {month} {day}, {year}": "Objave za {day}. {month}, {year}", "Posts for {month} {year}": "Objave za {month} {year}", "Previous post": "Prejšnja objava", "Publication date": "Datum objave", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "Več o tem", "Skip to main content": "Preskoči na glavno vsebino", "Source": "Izvor", + "Subcategories:": "", "Tags and Categories": "Značke in kategorije", "Tags": "Značke", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "stare objave, stran %d", "page %d": "stran %d", } diff --git a/nikola/data/themes/base/messages/messages_sr.py b/nikola/data/themes/base/messages/messages_sr.py new file mode 100644 index 0000000..6087027 --- /dev/null +++ b/nikola/data/themes/base/messages/messages_sr.py @@ -0,0 +1,39 @@ +# -*- encoding:utf-8 -*- +from __future__ import unicode_literals + +MESSAGES = { + "%d min remaining to read": "%d минута је преостало за читање", + "(active)": "", + "Also available in:": "Такође доступан у:", + "Archive": "Архива", + "Categories": "Категорије", + "Comments": "Коментари", + "LANGUAGE": "Српски", + "Languages:": "Језици:", + "More posts about %s": "Више постова о %s", + "Newer posts": "Новији постови", + "Next post": "Следећи пост", + "No posts found.": "Нема постова.", + "Nothing found.": "Није ништа пронађено.", + "Older posts": "Старији постови", + "Original site": "Оригинал сајт", + "Posted:": "Објављено:", + "Posts about %s": "Постови о %s", + "Posts for year %s": "Постови за годину %s", + "Posts for {month} {day}, {year}": "", + "Posts for {month} {year}": "Постови за {month} {year}", + "Previous post": "Претходни пост", + "Publication date": "Датум објаве", + "RSS feed": "RSS feed", + "Read in English": "Прочитај на српском", + "Read more": "Прочитај више", + "Skip to main content": "Прескочи на главни садржај", + "Source": "Извор", + "Subcategories:": "", + "Tags and Categories": "Тагови и категорије", + "Tags": "Тагови", + "Write your page here.": "", + "Write your post here.": "", + "old posts, page %d": "стари постови, страна %d", + "page %d": "страна %d", +} diff --git a/nikola/data/themes/base/messages/messages_sv.py b/nikola/data/themes/base/messages/messages_sv.py new file mode 100644 index 0000000..deda21a --- /dev/null +++ b/nikola/data/themes/base/messages/messages_sv.py @@ -0,0 +1,39 @@ +# -*- encoding:utf-8 -*- +from __future__ import unicode_literals + +MESSAGES = { + "%d min remaining to read": "%d minuter kvar att läsa", + "(active)": "", + "Also available in:": "Även tillgänglig på:", + "Archive": "Arkiv", + "Categories": "Kategorier", + "Comments": "Kommentarer", + "LANGUAGE": "Svenska", + "Languages:": "Språk:", + "More posts about %s": "Mer inlägg om %s", + "Newer posts": "Nya inlägg", + "Next post": "Nästa inlägg", + "No posts found.": "Inga inlägg hittade", + "Nothing found.": "Inget hittat", + "Older posts": "Äldre inlägg", + "Original site": "Orgnialsida", + "Posted:": "Publicerad", + "Posts about %s": "Inlägg om %s", + "Posts for year %s": "Inlägg för år %s", + "Posts for {month} {day}, {year}": "Inlägg för {month} {day}, {year}", + "Posts for {month} {year}": "Inlägg för {month} {year}", + "Previous post": "Föregående inlägg", + "Publication date": "Publiceringsdatum", + "RSS feed": "RSS flöde", + "Read in English": "Läs på Svenska", + "Read more": "Läs mer", + "Skip to main content": "hoppa till huvudinehåll", + "Source": "Källa", + "Subcategories:": "Underkategorier:", + "Tags and Categories": "Taggar och Kategorier", + "Tags": "Taggar", + "Write your page here.": "", + "Write your post here.": "", + "old posts, page %d": "gamla inlägg, sida %d", + "page %d": "sida %d", +} diff --git a/nikola/data/themes/base/messages/messages_tl.py b/nikola/data/themes/base/messages/messages_tl.py new file mode 100644 index 0000000..f748edd --- /dev/null +++ b/nikola/data/themes/base/messages/messages_tl.py @@ -0,0 +1,39 @@ +# -*- encoding:utf-8 -*- +from __future__ import unicode_literals + +MESSAGES = { + "%d min remaining to read": "", + "(active)": "", + "Also available in:": "", + "Archive": "", + "Categories": "", + "Comments": "", + "LANGUAGE": "Ingles", + "Languages:": "Mga Wika:", + "More posts about %s": "", + "Newer posts": "", + "Next post": "Susunod", + "No posts found.": "", + "Nothing found.": "", + "Older posts": "", + "Original site": "", + "Posted:": "", + "Posts about %s": "", + "Posts for year %s": "", + "Posts for {month} {day}, {year}": "", + "Posts for {month} {year}": "", + "Previous post": "", + "Publication date": "", + "RSS feed": "", + "Read in English": "", + "Read more": "", + "Skip to main content": "", + "Source": "", + "Subcategories:": "", + "Tags and Categories": "", + "Tags": "Mga Tag", + "Write your page here.": "", + "Write your post here.": "", + "old posts, page %d": "", + "page %d": "", +} diff --git a/nikola/data/themes/base/messages/messages_tr.py b/nikola/data/themes/base/messages/messages_tr.py index 3ba8217..21eb534 100644 --- a/nikola/data/themes/base/messages/messages_tr.py +++ b/nikola/data/themes/base/messages/messages_tr.py @@ -2,7 +2,8 @@ from __future__ import unicode_literals MESSAGES = { - "%d min remaining to read": "", + "%d min remaining to read": "%d dakikalık okuma", + "(active)": "", "Also available in:": "Şu dilde de mevcut:", "Archive": "Arşiv", "Categories": "Kategoriler", @@ -19,16 +20,20 @@ MESSAGES = { "Posted:": "Yayın tarihi:", "Posts about %s": "%s ile ilgili yazılar", "Posts for year %s": "%s yılındaki yazılar", + "Posts for {month} {day}, {year}": "{month} {day}, {year} 'den beri olan yazılar", "Posts for {month} {year}": "{month} {year} göre yazılar", "Previous post": "Önceki yazı", "Publication date": "Yayınlanma tarihi", "RSS feed": "RSS kaynağı", "Read in English": "Türkçe olarak oku", "Read more": "Devamını oku", - "Skip to main content": "", + "Skip to main content": "Ana içeriğe geç", "Source": "Kaynak", + "Subcategories:": "", "Tags and Categories": "Etiketler ve Kategoriler", "Tags": "Etiketler", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "eski yazılar, sayfa %d", "page %d": "sayfa %d", } diff --git a/nikola/data/themes/base/messages/messages_uk.py b/nikola/data/themes/base/messages/messages_uk.py new file mode 100644 index 0000000..16913da --- /dev/null +++ b/nikola/data/themes/base/messages/messages_uk.py @@ -0,0 +1,39 @@ +# -*- encoding:utf-8 -*- +from __future__ import unicode_literals + +MESSAGES = { + "%d min remaining to read": "Залишилось читати %d хвилин", + "(active)": "", + "Also available in:": "Іншою мовою:", + "Archive": "Архів", + "Categories": "Категорії", + "Comments": "Коментарі", + "LANGUAGE": "Українська", + "Languages:": "Мови:", + "More posts about %s": "Більше статей про %s", + "Newer posts": "Нові статті", + "Next post": "Наступна стаття", + "No posts found.": "Не знайдено жодної статті", + "Nothing found.": "Нічого не знайдено", + "Older posts": "Більш старі статті", + "Original site": "Оригінал сайту", + "Posted:": "Опублікована:", + "Posts about %s": "Статті про %s", + "Posts for year %s": "Статті за %s рік", + "Posts for {month} {day}, {year}": "Статті за {month} {day}, {year}", + "Posts for {month} {year}": "Статті за {month} {year}", + "Previous post": "Попередня стаття", + "Publication date": "Дата публікації", + "RSS feed": "RSS-стрічка", + "Read in English": "Читати українською", + "Read more": "Читати далі", + "Skip to main content": "Перейти до основного матеріалу", + "Source": "Джерело", + "Subcategories:": "", + "Tags and Categories": "Теги і категорії", + "Tags": "Теги", + "Write your page here.": "", + "Write your post here.": "", + "old posts, page %d": "старі статті, сторінка %d", + "page %d": "сторінка %d", +} diff --git a/nikola/data/themes/base/messages/messages_ur.py b/nikola/data/themes/base/messages/messages_ur.py index fac2a3e..075606c 100644 --- a/nikola/data/themes/base/messages/messages_ur.py +++ b/nikola/data/themes/base/messages/messages_ur.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "%d منٹ کا مطالعہ باقی", + "(active)": "", "Also available in:": "ان زبانوں میں بھی دستیاب:", "Archive": "آرکائیو", "Categories": "زمرے", @@ -19,16 +20,20 @@ MESSAGES = { "Posted:": "اشاعت:", "Posts about %s": "%s کے بارے میں تحاریر", "Posts for year %s": "سال %s کی تحاریر", + "Posts for {month} {day}, {year}": "{day} {month}، {year} کی تحاریر", "Posts for {month} {year}": "{month} {year} کی تحاریر", "Previous post": "پچھلی تحریر", "Publication date": "تاریخِ اشاعت", "RSS feed": "آر ایس ایس فیڈ", - "Read in English": "اردو میں پڑھیے", - "Read more": "مزید پڑھیے", - "Skip to main content": "", + "Read in English": "اردو میں پڑھیں", + "Read more": "مزید پڑھیں", + "Skip to main content": "مرکزی متن پر جائیں", "Source": "سورس", + "Subcategories:": "ذیلی زمرے", "Tags and Categories": "ٹیگز اور زمرے", "Tags": "ٹیگز", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "پرانی تحاریر صفحہ %d", "page %d": "صفحہ %d", } diff --git a/nikola/data/themes/base/messages/messages_zh_cn.py b/nikola/data/themes/base/messages/messages_zh_cn.py index 9d36505..c21b4f0 100644 --- a/nikola/data/themes/base/messages/messages_zh_cn.py +++ b/nikola/data/themes/base/messages/messages_zh_cn.py @@ -3,6 +3,7 @@ from __future__ import unicode_literals MESSAGES = { "%d min remaining to read": "", + "(active)": "", "Also available in:": "其他语言版本:", "Archive": "文章存档", "Categories": "分类", @@ -19,6 +20,7 @@ MESSAGES = { "Posted:": "发表于:", "Posts about %s": "文章分类:%s", "Posts for year %s": "%s年文章", + "Posts for {month} {day}, {year}": "", "Posts for {month} {year}": "{year}年{month}月文章", "Previous post": "前一篇", "Publication date": "", @@ -27,8 +29,11 @@ MESSAGES = { "Read more": "更多", "Skip to main content": "", "Source": "源代码", + "Subcategories:": "", "Tags and Categories": "标签和分类", "Tags": "标签", + "Write your page here.": "", + "Write your post here.": "", "old posts, page %d": "旧文章页 %d", "page %d": "", } diff --git a/nikola/data/themes/base/messages/messages_zh_tw.py b/nikola/data/themes/base/messages/messages_zh_tw.py new file mode 100644 index 0000000..fd26d77 --- /dev/null +++ b/nikola/data/themes/base/messages/messages_zh_tw.py @@ -0,0 +1,39 @@ +# -*- encoding:utf-8 -*- +from __future__ import unicode_literals + +MESSAGES = { + "%d min remaining to read": "", + "(active)": "", + "Also available in:": "", + "Archive": "", + "Categories": "", + "Comments": "", + "LANGUAGE": "", + "Languages:": "", + "More posts about %s": "", + "Newer posts": "", + "Next post": "", + "No posts found.": "", + "Nothing found.": "", + "Older posts": "", + "Original site": "", + "Posted:": "", + "Posts about %s": "", + "Posts for year %s": "", + "Posts for {month} {day}, {year}": "", + "Posts for {month} {year}": "", + "Previous post": "", + "Publication date": "", + "RSS feed": "", + "Read in English": "", + "Read more": "", + "Skip to main content": "", + "Source": "", + "Subcategories:": "", + "Tags and Categories": "", + "Tags": "", + "Write your page here.": "", + "Write your post here.": "", + "old posts, page %d": "", + "page %d": "", +} diff --git a/nikola/data/themes/base/templates/archiveindex.tmpl b/nikola/data/themes/base/templates/archiveindex.tmpl new file mode 100644 index 0000000..129b7c4 --- /dev/null +++ b/nikola/data/themes/base/templates/archiveindex.tmpl @@ -0,0 +1,13 @@ +## -*- coding: utf-8 -*- +<%inherit file="index.tmpl"/> + +<%block name="extra_head"> + ${parent.extra_head()} + %if len(translations) > 1 and generate_atom: + %for language in translations: + <link rel="alternate" type="application/atom+xml" title="Atom for the ${archive_name} section (${language})" href="${_link("archive_atom", archive_name, language)}"> + %endfor + %elif generate_atom: + <link rel="alternate" type="application/atom+xml" title="Atom for the ${archive_name} archive" href="${_link("archive_atom", archive_name)}"> + %endif +</%block> diff --git a/nikola/data/themes/base/templates/base.tmpl b/nikola/data/themes/base/templates/base.tmpl index 21f5ad5..6da6416 100644 --- a/nikola/data/themes/base/templates/base.tmpl +++ b/nikola/data/themes/base/templates/base.tmpl @@ -14,7 +14,7 @@ ${template_hooks['extra_head']()} <a href="#content" class="sr-only sr-only-focusable">${messages("Skip to main content")}</a> <div id="container"> ${header.html_header()} - <main id="content"> + <main id="content" role="main"> <%block name="content"></%block> </main> ${footer.html_footer()} diff --git a/nikola/data/themes/base/templates/base_header.tmpl b/nikola/data/themes/base/templates/base_header.tmpl index 0c6e12d..0c19af6 100644 --- a/nikola/data/themes/base/templates/base_header.tmpl +++ b/nikola/data/themes/base/templates/base_header.tmpl @@ -16,7 +16,7 @@ </%def> <%def name="html_site_title()"> - <h1 id="brand"><a href="${abs_link('/')}" title="${blog_title}" rel="home"> + <h1 id="brand"><a href="${abs_link(_link("root", None, lang))}" title="${blog_title}" rel="home"> %if logo_url: <img src="${logo_url}" alt="${blog_title}" id="logo"> %endif @@ -36,7 +36,7 @@ <ul> %for suburl, text in url: % if rel_link(permalink, suburl) == "#": - <li class="active"><a href="${permalink}">${text}</a></li> + <li class="active"><a href="${permalink}">${text} <span class="sr-only">${messages("(active)", lang)}</span></a></li> %else: <li><a href="${suburl}">${text}</a></li> %endif @@ -44,7 +44,7 @@ </ul> % else: % if rel_link(permalink, url) == "#": - <li class="active"><a href="${permalink}">${text}</a></li> + <li class="active"><a href="${permalink}">${text} <span class="sr-only">${messages("(active)", lang)}</span></a></li> %else: <li><a href="${url}">${text}</a></li> %endif diff --git a/nikola/data/themes/base/templates/base_helper.tmpl b/nikola/data/themes/base/templates/base_helper.tmpl index 491b6da..28b3f8a 100644 --- a/nikola/data/themes/base/templates/base_helper.tmpl +++ b/nikola/data/themes/base/templates/base_helper.tmpl @@ -2,28 +2,24 @@ <%def name="html_headstart()"> <!DOCTYPE html> -<html -\ -% if use_open_graph or (twitter_card and twitter_card['use_twitter_cards']) or (comment_system == 'facebook'): +<html \ prefix='\ %if use_open_graph or (twitter_card and twitter_card['use_twitter_cards']): -og: http://ogp.me/ns# \ -%endif -%if use_open_graph: -article: http://ogp.me/ns/article# \ +og: http://ogp.me/ns# article: http://ogp.me/ns/article# \ %endif %if comment_system == 'facebook': -fb: http://ogp.me/ns/fb# \ +fb: http://ogp.me/ns/fb# %endif -'\ +' \ +%if use_open_graph or (twitter_card and twitter_card['use_twitter_cards']): +vocab="http://ogp.me/ns" \ %endif -\ % if is_rtl: dir="rtl" \ % endif \ lang="${lang}"> - <head> +<head> <meta charset="utf-8"> %if description: <meta name="description" content="${description}"> @@ -83,6 +79,10 @@ lang="${lang}"> <link href="/assets/css/custom.css" rel="stylesheet" type="text/css"> %endif %endif + % if needs_ipython_css: + <link href="/assets/css/ipython.min.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/nikola_ipython.css" rel="stylesheet" type="text/css"> + % endif </%def> <%def name="html_feedlinks()"> @@ -97,13 +97,22 @@ lang="${lang}"> <link rel="alternate" type="application/rss+xml" title="RSS" href="${_link('rss', None)}"> %endif %endif + %if generate_atom: + %if len(translations) > 1: + %for language in translations: + <link rel="alternate" type="application/atom+xml" title="Atom (${language})" href="${_link('index_atom', None, language)}"> + %endfor + %else: + <link rel="alternate" type="application/atom+xml" title="Atom" href="${_link('index_atom', None)}"> + %endif + %endif </%def> <%def name="html_translations()"> <ul class="translations"> %for langname in translations.keys(): %if langname != lang: - <li><a href="${_link("index", None, langname)}" rel="alternate" hreflang="${langname}">${messages("LANGUAGE", langname)}</a></li> + <li><a href="${abs_link(_link("root", None, langname))}" rel="alternate" hreflang="${langname}">${messages("LANGUAGE", langname)}</a></li> %endif %endfor </ul> diff --git a/nikola/data/themes/base/templates/comments_helper_disqus.tmpl b/nikola/data/themes/base/templates/comments_helper_disqus.tmpl index 8a94eaf..6dd423c 100644 --- a/nikola/data/themes/base/templates/comments_helper_disqus.tmpl +++ b/nikola/data/themes/base/templates/comments_helper_disqus.tmpl @@ -1,10 +1,6 @@ ## -*- coding: utf-8 -*- -<%! - import json - translations = { - 'es': 'es_ES', - } -%> + +<%! import json %> <%def name="comment_form(url, title, identifier)"> %if comment_system_id: @@ -17,7 +13,11 @@ disqus_title=${json.dumps(title)}, disqus_identifier="${identifier}", disqus_config = function () { - this.language = "${translations.get(lang, lang)}"; + %if lang == 'es': + this.language = "es_ES"; + %else: + this.language = "${lang}"; + %endif }; (function() { var dsq = document.createElement('script'); dsq.async = true; diff --git a/nikola/data/themes/base/templates/crumbs.tmpl b/nikola/data/themes/base/templates/crumbs.tmpl index de8e570..49c5e1e 100644 --- a/nikola/data/themes/base/templates/crumbs.tmpl +++ b/nikola/data/themes/base/templates/crumbs.tmpl @@ -5,7 +5,13 @@ <nav class="breadcrumbs"> <ul class="breadcrumb"> % for link, text in crumbs: - <li><a href="${link}">${text}</a></li> + % if text != index_file: + % if link == '#': + <li>${text.rsplit('.html', 1)[0]}</li> + % else: + <li><a href="${link}">${text}</a></li> + % endif + % endif % endfor </ul> </nav> diff --git a/nikola/data/themes/base/templates/gallery.tmpl b/nikola/data/themes/base/templates/gallery.tmpl index ca9da05..0ee07ac 100644 --- a/nikola/data/themes/base/templates/gallery.tmpl +++ b/nikola/data/themes/base/templates/gallery.tmpl @@ -7,7 +7,7 @@ <%block name="content"> ${ui.bar(crumbs)} %if title: - <h1>${title}</h1> + <h1>${title|h}</h1> %endif %if post: <p> @@ -34,3 +34,8 @@ ${comments.comment_form(None, permalink, title)} %endif </%block> + +<%block name="extra_head"> +${parent.extra_head()} +<link rel="alternate" type="application/rss+xml" title="RSS" href="rss.xml"> +</%block> diff --git a/nikola/data/themes/base/templates/index.tmpl b/nikola/data/themes/base/templates/index.tmpl index e833eb0..69630e5 100644 --- a/nikola/data/themes/base/templates/index.tmpl +++ b/nikola/data/themes/base/templates/index.tmpl @@ -3,15 +3,23 @@ <%namespace name="comments" file="comments_helper.tmpl"/> <%inherit file="base.tmpl"/> +<%block name="extra_head"> + ${parent.extra_head()} + % if posts and (permalink == '/' or permalink == '/' + index_file): + <link rel="prefetch" href="${posts[0].permalink()}" type="text/html"> + % endif +</%block> + <%block name="content"> +<%block name="content_header"></%block> <div class="postindex"> % for post in posts: <article class="h-entry post-${post.meta('type')}"> <header> - <h1 class="p-name entry-title"><a href="${post.permalink()}" class="u-url">${post.title()}</h1></a> + <h1 class="p-name entry-title"><a href="${post.permalink()}" class="u-url">${post.title()|h}</a></h1> <div class="metadata"> <p class="byline author vcard"><span class="byline-name fn">${post.author()}</span></p> - <p class="dateline"><a href="${post.permalink()}" rel="bookmark"><time class="published dt-published" datetime="${post.date.isoformat()}" itemprop="datePublished" title="${messages("Publication date")}">${post.formatted_date(date_format)}</time></a></p> + <p class="dateline"><a href="${post.permalink()}" rel="bookmark"><time class="published dt-published" datetime="${post.date.isoformat()}" title="${post.formatted_date(date_format)}">${post.formatted_date(date_format)}</time></a></p> % if not post.meta('nocomments') and site_has_comments: <p class="commentline">${comments.comment_link(post.permalink(), post._base_path)} % endif diff --git a/nikola/data/themes/base/templates/list_post.tmpl b/nikola/data/themes/base/templates/list_post.tmpl index 0ef164f..4fb497c 100644 --- a/nikola/data/themes/base/templates/list_post.tmpl +++ b/nikola/data/themes/base/templates/list_post.tmpl @@ -9,7 +9,7 @@ %if posts: <ul class="postlist"> % for post in posts: - <li><a href="${post.permalink()}" class="listtitle">${post.title()}</a> <time class="listdate" datetime="${post.date.isoformat()}" title="${messages("Publication date")}">${post.formatted_date(date_format)}</time></li> + <li><a href="${post.permalink()}" class="listtitle">${post.title()|h}</a> <time class="listdate" datetime="${post.date.isoformat()}" title="${post.formatted_date(date_format)}">${post.formatted_date(date_format)}</time></li> % endfor </ul> %else: diff --git a/nikola/data/themes/base/templates/post.tmpl b/nikola/data/themes/base/templates/post.tmpl index fc0afba..cbb81ef 100644 --- a/nikola/data/themes/base/templates/post.tmpl +++ b/nikola/data/themes/base/templates/post.tmpl @@ -10,15 +10,18 @@ <meta name="keywords" content="${post.meta('keywords')|h}"> % endif %if post.description(): - <meta name="description" itemprop="description" content="${post.description()}"> + <meta name="description" content="${post.description()}"> %endif <meta name="author" content="${post.author()}"> %if post.prev_post: - <link rel="prev" href="${post.prev_post.permalink()}" title="${post.prev_post.title()}" type="text/html"> + <link rel="prev" href="${post.prev_post.permalink()}" title="${post.prev_post.title()|h}" type="text/html"> %endif %if post.next_post: - <link rel="next" href="${post.next_post.permalink()}" title="${post.next_post.title()}" type="text/html"> + <link rel="next" href="${post.next_post.permalink()}" title="${post.next_post.title()|h}" type="text/html"> %endif + % if post.is_draft: + <meta name="robots" content="noindex"> + % endif ${helper.open_graph_metadata(post)} ${helper.twitter_card_information(post)} ${helper.meta_translations(post)} @@ -37,7 +40,7 @@ </nav> </aside> % if not post.meta('nocomments') and site_has_comments: - <section class="comments"> + <section class="comments hidden-print"> <h2>${messages("Comments")}</h2> ${comments.comment_form(post.permalink(absolute=True), post.title(), post._base_path)} </section> diff --git a/nikola/data/themes/base/templates/post_header.tmpl b/nikola/data/themes/base/templates/post_header.tmpl index c848186..0efb2f8 100644 --- a/nikola/data/themes/base/templates/post_header.tmpl +++ b/nikola/data/themes/base/templates/post_header.tmpl @@ -4,12 +4,12 @@ <%def name="html_title()"> %if title and not post.meta('hidetitle'): - <h1 class="p-name entry-title" itemprop="headline name"><a href="${post.permalink()}" class="u-url">${title|h}</a></h1> + <h1 class="p-name entry-title" itemprop="headline name"><a href="${post.permalink()}" class="u-url">${post.title()|h}</a></h1> %endif </%def> <%def name="html_translations(post)"> - % if len(translations) > 1: + % if len(post.translated_to) > 1: <div class="metadata posttranslations translations"> <h3 class="posttranslations-intro">${messages("Also available in:")}</h3> % for langname in translations.keys(): @@ -32,13 +32,13 @@ ${html_title()} <div class="metadata"> <p class="byline author vcard"><span class="byline-name fn">${post.author()}</span></p> - <p class="dateline"><a href="${post.permalink()}" rel="bookmark"><time class="published dt-published" datetime="${post.date.isoformat()}" itemprop="datePublished" title="${messages("Publication date")}">${post.formatted_date(date_format)}</time></a></p> + <p class="dateline"><a href="${post.permalink()}" rel="bookmark"><time class="published dt-published" datetime="${post.date.isoformat()}" itemprop="datePublished" title="${post.formatted_date(date_format)}">${post.formatted_date(date_format)}</time></a></p> % if not post.meta('nocomments') and site_has_comments: <p class="commentline">${comments.comment_link(post.permalink(), post._base_path)} % endif ${html_sourcelink()} % if post.meta('link'): - <p><a href='${post.meta('link')}'>${messages("Original site")}</a></p> + <p class="linkline"><a href='${post.meta('link')}'>${messages("Original site")}</a></p> % endif %if post.description(): <meta name="description" itemprop="description" content="${post.description()}"> diff --git a/nikola/data/themes/base/templates/post_helper.tmpl b/nikola/data/themes/base/templates/post_helper.tmpl index c4e0ed1..e091447 100644 --- a/nikola/data/themes/base/templates/post_helper.tmpl +++ b/nikola/data/themes/base/templates/post_helper.tmpl @@ -14,7 +14,9 @@ %if post.tags: <ul itemprop="keywords" class="tags"> %for tag in post.tags: - <li><a class="tag p-category" href="${_link('tag', tag)}" rel="tag">${tag}</a></li> + % if tag not in hidden_tags: + <li><a class="tag p-category" href="${_link('tag', tag)}" rel="tag">${tag}</a></li> + % endif %endfor </ul> %endif @@ -22,15 +24,15 @@ <%def name="html_pager(post)"> %if post.prev_post or post.next_post: - <ul class="pager"> + <ul class="pager hidden-print"> %if post.prev_post: <li class="previous"> - <a href="${post.prev_post.permalink()}" rel="prev" title="${post.prev_post.title()}">${messages("Previous post")}</a> + <a href="${post.prev_post.permalink()}" rel="prev" title="${post.prev_post.title()|h}">${messages("Previous post")}</a> </li> %endif %if post.next_post: <li class="next"> - <a href="${post.next_post.permalink()}" rel="next" title="${post.next_post.title()}">${messages("Next post")}</a> + <a href="${post.next_post.permalink()}" rel="next" title="${post.next_post.title()|h}">${messages("Next post")}</a> </li> %endif </ul> @@ -39,15 +41,30 @@ <%def name="open_graph_metadata(post)"> %if use_open_graph: - <meta name="og:title" content="${post.title()[:70]|h}"> - <meta name="og:url" content="${abs_link(permalink)}"> + <meta property="og:site_name" content="${blog_title|striphtml}"> + <meta property="og:title" content="${post.title()[:70]|h}"> + <meta property="og:url" content="${abs_link(permalink)}"> %if post.description(): - <meta name="og:description" content="${post.description()[:200]|h}"> + <meta property="og:description" content="${post.description()[:200]|h}"> %else: - <meta name="og:description" content="${post.text(strip_html=True)[:200]|h}"> + <meta property="og:description" content="${post.text(strip_html=True)[:200]|h}"> + %endif + %if post.previewimage: + <meta property="og:image" content="${url_replacer(permalink, post.previewimage, lang, 'absolute')}"> + %endif + <meta property="og:type" content="article"> +### Will only work with Pintrest and breaks everywhere else who expect a [Facebook] URI. +### %if post.author(): +### <meta property="article:author" content="${post.author()}"> +### %endif + %if post.date.isoformat(): + <meta property="article:published_time" content="${post.date.isoformat()}"> + %endif + %if post.tags: + %for tag in post.tags: + <meta property="article:tag" content="${tag}"> + %endfor %endif - <meta name="og:site_name" content="${blog_title|striphtml}"> - <meta name="og:type" content="article"> %endif </%def> diff --git a/nikola/data/themes/base/templates/post_list_directive.tmpl b/nikola/data/themes/base/templates/post_list_directive.tmpl index d9166e9..e080a81 100644 --- a/nikola/data/themes/base/templates/post_list_directive.tmpl +++ b/nikola/data/themes/base/templates/post_list_directive.tmpl @@ -8,7 +8,7 @@ <li class="post-list-item"> ${post.formatted_date(date_format)} - <a href="${post.permalink(lang)}">${post.title(lang)}</a> + <a href="${post.permalink(lang)}">${post.title(lang)|h}</a> </li> % endfor </ul> diff --git a/nikola/data/themes/base/templates/tag.tmpl b/nikola/data/themes/base/templates/tag.tmpl index bff82c2..ec5caca 100644 --- a/nikola/data/themes/base/templates/tag.tmpl +++ b/nikola/data/themes/base/templates/tag.tmpl @@ -16,7 +16,18 @@ <%block name="content"> <article class="tagpage"> <header> - <h1>${title}</h1> + <h1>${title|h}</h1> + %if description: + <p>${description}</p> + %endif + %if subcategories: + ${messages('Subcategories:')} + <ul> + %for name, link in subcategories: + <li><a href="${link}">${name}</a></li> + %endfor + </ul> + %endif <div class="metadata"> %if len(translations) > 1 and generate_rss: %for language in translations: @@ -32,7 +43,7 @@ %if posts: <ul class="postlist"> % for post in posts: - <li><a href="${post.permalink()}" class="listtitle">${post.title()}</a> <time class="listdate" datetime="${post.date.isoformat()}" title="${messages("Publication date")}">${post.formatted_date(date_format)}</time></li> + <li><a href="${post.permalink()}" class="listtitle">${post.title()|h}</a> <time class="listdate" datetime="${post.date.isoformat()}" title="${post.formatted_date(date_format)}">${post.formatted_date(date_format)}</time></li> % endfor </ul> %endif diff --git a/nikola/data/themes/base/templates/tagindex.tmpl b/nikola/data/themes/base/templates/tagindex.tmpl index 9dda70a..7160fe9 100644 --- a/nikola/data/themes/base/templates/tagindex.tmpl +++ b/nikola/data/themes/base/templates/tagindex.tmpl @@ -1,2 +1,24 @@ ## -*- coding: utf-8 -*- <%inherit file="index.tmpl"/> + +<%block name="content_header"> + %if subcategories: + ${messages('Subcategories:')} + <ul> + %for name, link in subcategories: + <li><a href="${link}">${name}</a></li> + %endfor + </ul> + %endif +</%block> + +<%block name="extra_head"> + ${parent.extra_head()} + %if len(translations) > 1 and generate_atom: + %for language in translations: + <link rel="alternate" type="application/atom+xml" title="Atom for the ${tag} section (${language})" href="${_link(kind + "_atom", tag, language)}"> + %endfor + %elif generate_atom: + <link rel="alternate" type="application/atom+xml" title="Atom for the ${tag} section" href="${_link("tag" + "_atom", tag)}"> + %endif +</%block> diff --git a/nikola/data/themes/base/templates/tags.tmpl b/nikola/data/themes/base/templates/tags.tmpl index 3e0c4b4..a9d2dd7 100644 --- a/nikola/data/themes/base/templates/tags.tmpl +++ b/nikola/data/themes/base/templates/tags.tmpl @@ -7,14 +7,24 @@ <h1>${title}</h1> </header> % if cat_items: - <h2>${messages("Categories")}</h2> - <ul class="postlist"> - % for text, link in cat_items: - % if text: - <li><a class="reference" href="${link}">${text}</a></li> + % if items: + <h2>${messages("Categories")}</h2> + % endif + % for text, full_name, path, link, indent_levels, indent_change_before, indent_change_after in cat_hierarchy: + % for i in range(indent_change_before): + <ul class="postlist"> + % endfor + <li><a class="reference" href="${link}">${text}</a> + % if indent_change_after <= 0: + </li> % endif + % for i in range(-indent_change_after): + </ul> + % if i + 1 < len(indent_levels): + </li> + % endif + % endfor % endfor - </ul> % if items: <h2>${messages("Tags")}</h2> % endif @@ -22,7 +32,9 @@ % if items: <ul class="postlist"> % for text, link in items: - <li><a class="reference listtitle" href="${link}">${text}</a></li> + % if text not in hidden_tags: + <li><a class="reference listtitle" href="${link}">${text}</a></li> + % endif % endfor </ul> % endif diff --git a/nikola/data/themes/bootstrap-jinja/README.md b/nikola/data/themes/bootstrap-jinja/README.md index 5340fe2..637caf5 100644 --- a/nikola/data/themes/bootstrap-jinja/README.md +++ b/nikola/data/themes/bootstrap-jinja/README.md @@ -3,7 +3,7 @@ A "website-done-with-bootstrap" theme, so to speak. Has a fixed navigation bar at top that displays the NAVIGATION_LINKS setting and supports nested menus. -This theme is used in Nikola's website: http://getnikola.com +This theme is used in Nikola's website: https://getnikola.com Important: To fit in the bootstrap navigation bar, the search form needs the navbar-form and pull-left CSS classes applied. Here is an example with Nikola's diff --git a/nikola/data/themes/bootstrap-jinja/assets/css/theme.css b/nikola/data/themes/bootstrap-jinja/assets/css/theme.css index 7566a80..4fc31a8 120000..100644 --- a/nikola/data/themes/bootstrap-jinja/assets/css/theme.css +++ b/nikola/data/themes/bootstrap-jinja/assets/css/theme.css @@ -1 +1,205 @@ -../../../bootstrap/assets/css/theme.css
\ No newline at end of file +#container { + width: 960px; + margin: 50 auto; +} + +#contentcolumn { + max-width: 760px; +} +#q { + width: 150px; +} + +img { + max-width: 90%; +} + +.postbox { + border-bottom: 2px solid darkgrey; + margin-bottom: 12px; +} + +.footerbox {padding: 15px; text-align: center; margin-bottom: 15px;} + +td.label { + /* Issue #290 */ + background-color: inherit; +} + +.footnote-reference { + /* Issue 290 */ + vertical-align: super; + font-size: xx-small; +} + +.caption { + /* Issue 292 */ + text-align: center; + padding-top: 1em; +} + +div.figure > img, +div.figure > a > img { + /* Issue 292 */ + display: block; + margin-left: auto; + margin-right: auto; +} + +div.sidebar, div.admonition, div.attention, div.caution, div.danger, div.error, div.hint, div.important, div.note, div.tip, div.warning { + /* Issue 277 */ + border: 1px solid #aaa; + border-radius: 5px; +} + +blockquote p, blockquote { + font-size: 17.5px; + font-weight: 300; + line-height: 1.25; +} + +ul.bricks > li { + display: inline; + background-color: lightblue; + padding: 8px; + border-radius: 5px; + line-height: 3; + white-space:nowrap; + margin: 3px; +} + +ul.breadcrumb > li:before { + content: " / "; +} + +pre, pre code { + white-space: pre; + word-wrap: normal; + overflow: auto; +} + +article.post-micro { + font-family: Georgia, 'Times New Roman', Times, serif; + font-size: 1.5em; +} + +.image-block { + display: inline-block; +} + +.flowr_row { + width: 100%; +} + +.tags { + padding-left: 0; + margin-left: -5px; + list-style: none; + text-align: center; + +} + +.tags > li { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #999; + border-radius: 10px; +} + +.tags > li a { + color: #fff; +} + +.metadata p:before, +.postlist .listdate:before { + content: " — "; +} + +.metadata p:first-of-type:before { + content: ""; +} + +.metadata p { + display: inline; +} + +.posttranslations h3 { + display: inline; + font-size: 1em; + font-weight: bold; +} + +.posttranslations h3:last-child { + display: none; +} + +.entry-content { + margin-top: 1em; +} + +.navbar .brand { + padding: 0 20px; +} + +.navbar .brand #blog-title { + padding: 10px 0; + display: inline-block; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; +} + +.sr-only-focusable:active, +.sr-only-focusable:focus { + position: static; + width: auto; + height: auto; + margin: 0; + overflow: visible; + clip: auto; +} + +/* hat tip bootstrap/html5 boilerplate */ +@media print { + *, *:before, *:after { + font-family: Garamond, Junicode, serif; + } + + body { + font-size: 12pt; + } + + article .entry-title a[href]:after, + article .metadata a[href]:after, + article .tags a[href]:after { + content: ""; + } + + article .metadata .sourceline { + display: none; + } + + article .metadata .linkline a[href]:after { + content: " (" attr(href) ")"; + } + + .navbar { + display: none; + } +} diff --git a/nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-bn.js b/nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-bn.js new file mode 120000 index 0000000..9b995d8 --- /dev/null +++ b/nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-bn.js @@ -0,0 +1 @@ +../../../../../../../bower_components/jquery-colorbox/i18n/jquery.colorbox-bn.js
\ No newline at end of file diff --git a/nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-pt-BR.js b/nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-pt-BR.js new file mode 120000 index 0000000..e20bd38 --- /dev/null +++ b/nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-pt-BR.js @@ -0,0 +1 @@ +../../../../../../../bower_components/jquery-colorbox/i18n/jquery.colorbox-pt-BR.js
\ No newline at end of file diff --git a/nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-pt-br.js b/nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-pt-br.js deleted file mode 120000 index 76f289e..0000000 --- a/nikola/data/themes/bootstrap-jinja/assets/js/colorbox-i18n/jquery.colorbox-pt-br.js +++ /dev/null @@ -1 +0,0 @@ -../../../../../../../bower_components/jquery-colorbox/i18n/jquery.colorbox-pt-br.js
\ No newline at end of file diff --git a/nikola/data/themes/bootstrap-jinja/assets/js/flowr.plugin.js b/nikola/data/themes/bootstrap-jinja/assets/js/flowr.plugin.js index c195756..c0d986b 120000..100644 --- a/nikola/data/themes/bootstrap-jinja/assets/js/flowr.plugin.js +++ b/nikola/data/themes/bootstrap-jinja/assets/js/flowr.plugin.js @@ -1 +1,265 @@ -../../../bootstrap/assets/js/flowr.plugin.js
\ No newline at end of file +/** + * Flowr.js - Simple jQuery plugin to emulate Flickr's justified view + * For usage information refer to http://github.com/kalyan02/flowr-js + * + * + * @author: Kalyan Chakravarthy (http://KalyanChakravarthy.net) + * @version: v0.1 + */ +(function($){ + //$("#container2").css( 'border', '1px solid #ccc'); + $.fn.flowr = function(options) { + + $this = this; + var ROW_CLASS_NAME = 'flowr-row'; // Class name for the row of flowy + var MAX_LAST_ROW_GAP = 25; // If the width of last row is lesser than max-width, recalculation is needed + var NO_COPY_FIELDS = [ 'complete', 'data', 'responsive' ]; // these attributes will not be carried forward for append related calls + var DEFAULTS = { + 'data' : [], + 'padding' : 5, // whats the padding between flowy items + 'height' : 240, // Minimum height an image row should take + 'render' : null, // callback function to get the tag + 'append' : false, // TODO + 'widthAttr' : 'width', // a custom data structure can specify which attribute refers to height/width + 'heightAttr' : 'height', + 'maxScale' : 1.5, // In case there is only 1 elment in last row + 'maxWidth' : this.width()-1, // 1px is just for offset + 'itemWidth' : null, // callback function for width + 'itemHeight' : null, // callback function for height + 'complete' : null, // complete callback + 'rowClassName' : ROW_CLASS_NAME, + 'rows' : -1, // Maximum number of rows to render. -1 for no limit. + 'responsive' : true // make content responsive + }; + var settings = $.extend( DEFAULTS, options); + + // If data is being appended, we already have settings + // If we already have settings, retrieve them + if( settings.append && $this.data('lastSettings') ) { + lastSettings = $this.data('lastSettings'); + + // Copy over the settings from previous init + for( attr in DEFAULTS ) { + if( NO_COPY_FIELDS.indexOf(attr)<0 && settings[attr] == DEFAULTS[attr] ) { + settings[attr] = lastSettings[attr]; + } + } + + // Check if we have an incomplete last row + lastRow = $this.data('lastRow'); + if( lastRow.data.length > 0 && settings.maxWidth-lastRow.width > MAX_LAST_ROW_GAP ) { + // Prepend the incomplete row to newly loaded data and redraw + lastRowData = lastSettings.data.slice( lastSettings.data.length - lastRow.data.length - 1 ); + settings.data = lastRowData.concat(settings.data); + + // Remove the incomplete row + // TODO: Don't reload this stuff later. Reattach to new row. + $( '.' + settings.rowClassName + ':last', $this ).detach(); + } else { + // console.log( lastRow.data.length ); + // console.log( lastRow.width ); + } + } + + // only on the first initial call + if( !settings.responsive && !settings.append ) + $this.width( $this.width() ); + + // Basic sanity checks + if( !(settings.data instanceof Array) ) + return; + + if( typeof(settings.padding) != 'number' ) + settings.padding = parseInt( settings.padding ); + + if( typeof(settings.itemWidth) != 'function' ) { + settings.itemWidth = function(data) { + return data[ settings.widthAttr ]; + } + } + + if( typeof(settings.itemHeight) != 'function' ) { + settings.itemHeight = function(data) { + return data[ settings.heightAttr ]; + } + } + + // A standalone utility to calculate the item widths for a particular row + // Returns rowWidth: width occupied & data : the items in the new row + var utils = { + getNextRow : function( data, settings ) { + var itemIndex = 0; + var itemsLength = data.length; + var lineItems = []; + var lineWidth = 0; + var maxWidth = settings.maxWidth; + var paddingSize = settings.padding; + + // console.log( 'maxItems=' + data.length ); + + requiredPadding = function() { + var extraPads = arguments.length == 1 ? arguments[0] : 0; + return (lineItems.length - 1 + extraPads) * settings.padding; + } + + while( lineWidth + requiredPadding() < settings.maxWidth && (itemIndex < itemsLength) ) { + var itemData = data[ itemIndex ]; + var itemWidth = settings.itemWidth.call( $this, itemData ); + var itemHeight = settings.itemHeight.call( $this, itemData ); + + var minHeight = settings.height; + var minWidth = Math.floor( itemWidth * settings.height / itemHeight ); + + var newLineWidth = lineWidth + minWidth + requiredPadding(1); + + if (minWidth > settings.maxWidth) { + // very short+wide images like panoramas + // show them even if ugly, as wide as possible + minWidth = settings.maxWidth-1; + minHeight = settings.height * minHeight / minWidth; + } + + // console.log( 'lineWidth = ' + lineWidth ); + // console.log( 'newLineWidth = ' + newLineWidth ); + if( newLineWidth < settings.maxWidth ) { + lineItems.push({ + 'height' : minHeight, + 'width' : minWidth, + 'itemData' : itemData + }); + + lineWidth += minWidth; + itemIndex ++; + } else { + // We'd have exceeded width. So break off to scale. + // console.log( 'breaking off = ' + itemIndex ); + // console.log( 'leave off size = ' + lineItems.length ); + break; + } + } //while + + // Scale the size to max width + testWidth=0; + if( lineWidth < settings.maxWidth ) { + var fullScaleWidth = settings.maxWidth - requiredPadding() - 10; + var currScaleWidth = lineWidth; + var scaleFactor = fullScaleWidth / currScaleWidth; + if( scaleFactor > settings.maxScale ) + scaleFactor = 1; + + var newHeight = Math.round( settings.height * scaleFactor ); + for( i=0; i<lineItems.length; i++ ) { + var lineItem = lineItems[ i ]; + lineItem.width = Math.floor(lineItem.width * scaleFactor); + lineItem.height = newHeight; + + testWidth += lineItem.width; + } + } + + return { + data : lineItems, + width : testWidth + requiredPadding() + }; + }, //getNextRow + reorderContent : function(){ + /* + TODO: optimize for faster resizing by reusing dom objects instead of killing the dom + */ + var _initialWidth = $this.data('width'); + var _newWidth = $this.width(); + var _change = _initialWidth - _newWidth; + + if(_initialWidth!=_newWidth) { + $this.html(''); + var _settings = $this.data( 'lastSettings' ); + _settings.data = $this.data( 'data' ); + _settings.maxWidth = $this.width() - 1; + $this.flowr( _settings ); + } + } + } //utils + + // If the resposive var is set to true then listen for resize method + // and prevent resizing from happening twice if responsive is set again during append phase! + if( settings.responsive && !$this.data('__responsive') ) { + $(window).resize(function(){ + initialWidth = $this.data('width'); + newWidth = $this.width(); + + //initiate resize + if( initialWidth != newWidth ) { + var task_id = $this.data('task_id'); + if( task_id ) { + task_id = clearTimeout( task_id ); + task_id = null; + } + task_id = setTimeout( utils.reorderContent, 80 ); + $this.data('task_id', task_id ); + } + }); + $this.data('__responsive',true); + } + + + return this.each(function(){ + + // Get a copy of original data. 1 level deep copy is sufficient. + var data = settings.data.slice(0); + var rowData = null; + var currentRow = 0; + var currentItem = 0; + + // Store all the data + var allData = $this.data( 'data' ) || []; + for(i=0;i<data.length;i++) { + allData.push( data[i] ); + } + $this.data( 'data', allData ); + + // While we have a new row + while( ( rowData = utils.getNextRow(data,settings) ) != null && rowData.data.length > 0 ) { + if( settings.rows > 0 && currentRow >= settings.rows ) + break; + // remove the number of elements in the new row from the top of data stack + data.splice( 0, rowData.data.length ); + + // Create a new row div, add class, append the htmls and insert the flowy items + var $row = $('<div>').addClass(settings.rowClassName); + for( i=0; i<rowData.data.length; i++ ) { + var displayData = rowData.data[i]; + // Get the HTML object from custom render function passed as argument + var displayObject = settings.render.call( $this, displayData ); + displayObject = $(displayObject); + // Set some basic stuff + displayObject + .css( 'width', displayData.width ) + .css( 'height', displayData.height ) + .css( 'margin-left', i==0 ? '0' : settings.padding + "px" ); //TODO:Refactor + $row.append( displayObject ); + + currentItem++; + } + $this.append( $row ); + // console.log ( "I> rowData.data.length="+rowData.data.length +" rowData.width="+rowData.width ); + + currentRow++; + $this.data('lastRow', rowData ); + } + // store the current state of settings and the items in last row + // we'll need this info when we append more items + $this.data('lastSettings', settings ); + + // onComplete callback + // pass back info about list of rows and items rendered + if( typeof (settings.complete) == 'function' ) { + var completeData = { + renderedRows : currentRow, + renderedItems : currentItem + } + settings.complete.call( $this, completeData ); + } + }); + }; + +})(jQuery); diff --git a/nikola/data/themes/bootstrap-jinja/assets/js/jquery.js b/nikola/data/themes/bootstrap-jinja/assets/js/jquery.js new file mode 120000 index 0000000..966173b --- /dev/null +++ b/nikola/data/themes/bootstrap-jinja/assets/js/jquery.js @@ -0,0 +1 @@ +../../../../../../bower_components/jquery/dist/jquery.js
\ No newline at end of file diff --git a/nikola/data/themes/bootstrap-jinja/templates/base.tmpl b/nikola/data/themes/bootstrap-jinja/templates/base.tmpl index e9bed3c..3177276 100644 --- a/nikola/data/themes/bootstrap-jinja/templates/base.tmpl +++ b/nikola/data/themes/bootstrap-jinja/templates/base.tmpl @@ -13,7 +13,7 @@ <!-- Menubar --> -<div class="navbar navbar-fixed-top" id="navbar"> +<div class="navbar navbar-static-top" id="navbar"> <div class="navbar-inner"> <div class="container"> @@ -24,7 +24,7 @@ <span class="icon-bar"></span> </a> - <a class="brand" href="{{ abs_link('/') }}"> + <a class="brand" href="{{ abs_link(_link("root", None, lang)) }}"> {% if logo_url %} <img src="{{ logo_url }}" alt="{{ blog_title }}" id="logo"> {% endif %} @@ -58,7 +58,7 @@ </div> </div> <!-- End of Menubar --> -<div class="container-fluid" id="content"> +<div class="container-fluid" id="content" role="main"> <!--Body content--> <div class="row-fluid"> <div class="span2"></div> @@ -74,7 +74,13 @@ {{ template_hooks['page_footer']() }} </div> {{ base.late_load_js() }} - <script>jQuery("a.image-reference").colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});</script> + <script>$('a.image-reference:not(.islink) img:not(.islink)').parent().colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});</script> + <!-- fancy dates --> + <script> + moment.locale("{{ momentjs_locales[lang] }}"); + fancydates({{ date_fanciness }}, {{ js_date_format }}); + </script> + <!-- end fancy dates --> {% block extra_js %}{% endblock %} {% if annotations and post and not post.meta('noannotations') %} {{ notes.code() }} diff --git a/nikola/data/themes/bootstrap-jinja/templates/base_helper.tmpl b/nikola/data/themes/bootstrap-jinja/templates/base_helper.tmpl index e44b3a7..4a29e69 100644 --- a/nikola/data/themes/bootstrap-jinja/templates/base_helper.tmpl +++ b/nikola/data/themes/bootstrap-jinja/templates/base_helper.tmpl @@ -1,5 +1,6 @@ {# -*- coding: utf-8 -*- #} +{% import 'annotation_helper.tmpl' as notes with context %} {% macro html_headstart() %} <!DOCTYPE html> <html @@ -68,19 +69,21 @@ lang="{{ lang }}"> {% macro late_load_js() %} {% if use_bundles %} {% if use_cdn %} - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> - <script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> + <script src="//maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script> <script src="/assets/js/all.js"></script> {% else %} <script src="/assets/js/all-nocdn.js"></script> {% endif %} {% else %} {% if use_cdn %} - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> - <script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> + <script src="//maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script> {% else %} <script src="/assets/js/jquery.min.js"></script> <script src="/assets/js/bootstrap.min.js"></script> + <script src="/assets/js/moment-with-locales.min.js"></script> + <script src="/assets/js/fancydates.js"></script> {% endif %} <script src="/assets/js/jquery.colorbox-min.js"></script> {% endif %} @@ -94,14 +97,14 @@ lang="{{ lang }}"> {% macro html_stylesheets() %} {% if use_bundles %} {% if use_cdn %} - <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet"> + <link href="//maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet"> <link href="/assets/css/all.css" rel="stylesheet" type="text/css"> {% else %} <link href="/assets/css/all-nocdn.css" rel="stylesheet" type="text/css"> {% endif %} {% else %} {% if use_cdn %} - <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet"> + <link href="//maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet"> {% else %} <link href="/assets/css/bootstrap.min.css" rel="stylesheet" type="text/css"> <link href="/assets/css/bootstrap-responsive.min.css" rel="stylesheet" type="text/css"> @@ -114,6 +117,10 @@ lang="{{ lang }}"> <link href="/assets/css/custom.css" rel="stylesheet" type="text/css"> {% endif %} {% endif %} + {% if needs_ipython_css %} + <link href="/assets/css/ipython.min.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/nikola_ipython.css" rel="stylesheet" type="text/css"> + {% endif %} {% if annotations and post and not post.meta('noannotations') %} {{ notes.css() }} {% elif not annotations and post and post.meta('annotations') %} @@ -129,7 +136,7 @@ lang="{{ lang }}"> <ul class="dropdown-menu"> {% for suburl, text in url %} {% if rel_link(permalink, suburl) == "#" %} - <li class="active"><a href="{{ permalink }}">{{ text }}</a> + <li class="active"><a href="{{ permalink }}">{{ text }} <span class="sr-only">{{ messages("(active)", lang) }}</span></a> {% else %} <li><a href="{{ suburl }}">{{ text }}</a> {% endif %} @@ -137,7 +144,7 @@ lang="{{ lang }}"> </ul> {% else %} {% if rel_link(permalink, url) == "#" %} - <li class="active"><a href="{{ permalink }}">{{ text }}</a> + <li class="active"><a href="{{ permalink }}">{{ text }} <span class="sr-only">{{ messages("(active)", lang) }}</span></a> {% else %} <li><a href="{{ url }}">{{ text }}</a> {% endif %} @@ -157,12 +164,21 @@ lang="{{ lang }}"> <link rel="alternate" type="application/rss+xml" title="RSS" href="{{ _link('rss', None) }}"> {% endif %} {% endif %} + {% if generate_atom %} + {% if translations|length > 1 %} + {% for language in translations %} + <link rel="alternate" type="application/atom+xml" title="Atom ({{ language }})" href="{{ _link('index_atom', None, language) }}"> + {% endfor %} + {% else %} + <link rel="alternate" type="application/atom+xml" title="Atom" href="{{ _link('index_atom', None) }}"> + {% endif %} + {% endif %} {% endmacro %} {% macro html_translations() %} {% for langname in translations.keys() %} {% if langname != lang %} - <li><a href="{{ _link("index", None, langname) }}" rel="alternate" hreflang="{{ langname }}">{{ messages("LANGUAGE", langname) }}</a></li> + <li><a href="{{ abs_link(_link("root", None, langname)) }}" rel="alternate" hreflang="{{ langname }}">{{ messages("LANGUAGE", langname) }}</a></li> {% endif %} {% endfor %} {% endmacro %} diff --git a/nikola/data/themes/bootstrap-jinja/templates/bootstrap_helper.tmpl b/nikola/data/themes/bootstrap-jinja/templates/bootstrap_helper.tmpl deleted file mode 100644 index e426774..0000000 --- a/nikola/data/themes/bootstrap-jinja/templates/bootstrap_helper.tmpl +++ /dev/null @@ -1,78 +0,0 @@ -{# -*- coding: utf-8 -*- #} -{# Override only the functions that differ from base_helper.tmpl #} - -{% block html_stylesheets %} - {% if use_bundles %} - {% if use_cdn %} - <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.0/css/bootstrap-combined.min.css" rel="stylesheet"> - <link href="/assets/css/all.css" rel="stylesheet" type="text/css"> - {% else %} - <link href="/assets/css/all-nocdn.css" rel="stylesheet" type="text/css"> - {% endif %} - {% else %} - {% if use_cdn %} - <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.0/css/bootstrap-combined.min.css" rel="stylesheet"> - {% else %} - <link href="/assets/css/bootstrap.min.css" rel="stylesheet" type="text/css"> - <link href="/assets/css/bootstrap-responsive.min.css" rel="stylesheet" type="text/css"> - {% endif %} - <link href="/assets/css/rst.css" rel="stylesheet" type="text/css"> - <link href="/assets/css/code.css" rel="stylesheet" type="text/css"> - <link href="/assets/css/colorbox.css" rel="stylesheet" type="text/css"/> - <link href="/assets/css/theme.css" rel="stylesheet" type="text/css"/> - {% if has_custom_css %} - <link href="/assets/css/custom.css" rel="stylesheet" type="text/css"> - {% endif %} - {% endif %} - {% if annotations and post and not post.meta('noannotations') %} - {{ notes.css() }} - {% elif not annotations and post and post.meta('annotations') %} - {{ notes.css() }} - {% endif %} -{% endblock %} - - -{% block late_load_js %} - {% if use_bundles %} - {% if use_cdn %} - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> - <script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.0/js/bootstrap.min.js"></script> - <script src="/assets/js/all.js"></script> - {% else %} - <script src="/assets/js/all-nocdn.js"></script> - {% endif %} - {% else %} - {% if use_cdn %} - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> - <script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.0/js/bootstrap.min.js"></script> - {% else %} - <script src="/assets/js/jquery-1.11.0.min.js"></script> - <script src="/assets/js/bootstrap.min.js"></script> - {% endif %} - <script src="/assets/js/jquery.colorbox-min.js"></script> - {% endif %} -{% endblock %} - - -{% block html_navigation_links %} - {% for url, text in navigation_links[lang] %} - {% if url is mapping %} - <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ text }}<b class="caret"></b></a> - <ul class="dropdown-menu"> - {% for suburl, text in url %} - {% if rel_link(permalink, suburl) == "#" %} - <li class="active"><a href="{{ permalink }}">{{ text }}</a> - {% else %} - <li><a href="{{ suburl }}">{{ text }}</a> - {% endif %} - {% endfor %} - </ul> - {% else %} - {% if rel_link(permalink, url) == "#" %} - <li class="active"><a href="{{ permalink }}">{{ text }}</a> - {% else %} - <li><a href="{{ url }}">{{ text }}</a> - {% endif %} - {% endif %} - {% endfor %} -{% endblock %} diff --git a/nikola/data/themes/bootstrap-jinja/templates/gallery.tmpl b/nikola/data/themes/bootstrap-jinja/templates/gallery.tmpl index e3f9f05..07112da 100644 --- a/nikola/data/themes/bootstrap-jinja/templates/gallery.tmpl +++ b/nikola/data/themes/bootstrap-jinja/templates/gallery.tmpl @@ -7,7 +7,7 @@ {% block content %} {{ ui.bar(crumbs) }} {% if title %} - <h1>{{ title }}</h1> + <h1>{{ title|e }}</h1> {% endif %} {% if post %} <p> @@ -40,6 +40,7 @@ {% block extra_head %} {{ super() }} +<link rel="alternate" type="application/rss+xml" title="RSS" href="rss.xml"> <style type="text/css"> .image-block { display: inline-block; diff --git a/nikola/data/themes/bootstrap-jinja/templates/post.tmpl b/nikola/data/themes/bootstrap-jinja/templates/post.tmpl index 54646d0..df4109c 100644 --- a/nikola/data/themes/bootstrap-jinja/templates/post.tmpl +++ b/nikola/data/themes/bootstrap-jinja/templates/post.tmpl @@ -14,10 +14,13 @@ {% endif %} <meta name="author" content="{{ post.author() }}"> {% if post.prev_post %} - <link rel="prev" href="{{ post.prev_post.permalink() }}" title="{{ post.prev_post.title() }}" type="text/html"> + <link rel="prev" href="{{ post.prev_post.permalink() }}" title="{{ post.prev_post.title()|e }}" type="text/html"> {% endif %} {% if post.next_post %} - <link rel="next" href="{{ post.next_post.permalink() }}" title="{{ post.next_post.title() }}" type="text/html"> + <link rel="next" href="{{ post.next_post.permalink() }}" title="{{ post.next_post.title()|e }}" type="text/html"> + {% endif %} + {% if post.is_draft %} + <meta name="robots" content="noindex"> {% endif %} {{ helper.open_graph_metadata(post) }} {{ helper.twitter_card_information(post) }} @@ -37,7 +40,7 @@ </nav> </aside> {% if not post.meta('nocomments') and site_has_comments %} - <section class="comments"> + <section class="comments hidden-print"> <h2>{{ messages("Comments") }}</h2> {{ comments.comment_form(post.permalink(absolute=True), post.title(), post._base_path) }} </section> diff --git a/nikola/data/themes/bootstrap-jinja/templates/post_header.tmpl b/nikola/data/themes/bootstrap-jinja/templates/post_header.tmpl deleted file mode 100644 index b565244..0000000 --- a/nikola/data/themes/bootstrap-jinja/templates/post_header.tmpl +++ /dev/null @@ -1,40 +0,0 @@ -{# -*- coding: utf-8 -*- #} -{% import 'post_helper.tmpl' as helper with context %} -{% import 'comments_helper.tmpl' as comments with context %} - -{% macro html_title() %} - <h1 class="p-name entry-title" itemprop="headline name"><a href="{{ post.permalink() }}" class="u-url">{{ title|e }}</a></h1> -{% endmacro %} - -{% macro html_translations(post) %} - {% if translations|length > 1 %} - <div class="metadata posttranslations translations"> - <h3 class="posttranslations-intro">{{ messages("Also available in:") }}</h3> - {% for langname in translations.keys() %} - {% if langname != lang and post.is_translation_available(langname) %} - <p><a href="{{ post.permalink(langname) }}" rel="alternate" hreflang="{{ langname }}">{{ messages("LANGUAGE", langname) }}</a></p> - {% endif %} - {% endfor %} - </div> - {% endif %} -{% endmacro %} - -{% macro html_post_header() %} - <header> - {{ html_title() }} - <div class="metadata"> - <p class="byline author vcard"><span class="byline-name fn">{{ post.author() }}</span></p> - <p class="dateline"><a href="{{ post.permalink() }}" rel="bookmark"><time class="published dt-published" datetime="{{ post.date.isoformat() }}" itemprop="datePublished" title="{{ messages("Publication date") }}">{{ post.formatted_date(date_format) }}</time></a></p> - {% if not post.meta('nocomments') and site_has_comments %} - <p class="commentline">{{ comments.comment_link(post.permalink(), post._base_path) }} - {% endif %} - {% if post.meta('link') %} - <p><a href='{{ post.meta('link') }}'>{{ messages("Original site") }}</a></p> - {% endif %} - {% if post.description() %} - <meta content="{{ post.description() }}" itemprop="description"> - {% endif %} - </div> - {{ html_translations(post) }} - </header> -{% endmacro %} diff --git a/nikola/data/themes/bootstrap-jinja/templates/tags.tmpl b/nikola/data/themes/bootstrap-jinja/templates/tags.tmpl index 080e621..c308f19 100644 --- a/nikola/data/themes/bootstrap-jinja/templates/tags.tmpl +++ b/nikola/data/themes/bootstrap-jinja/templates/tags.tmpl @@ -4,14 +4,24 @@ {% block content %} <h1>{{ title }}</h1> {% if cat_items %} - <h2>{{ messages("Categories") }}</h2> - <ul class="unstyled"> - {% for text, link in cat_items %} - {% if text %} - <li><a class="reference badge" href="{{ link }}">{{ text }}</a></li> + {% if items %} + <h2>{{ messages("Categories") }}</h2> + {% endif %} + {% for text, full_name, path, link, indent_levels, indent_change_before, indent_change_after in cat_hierarchy %} + {% for i in range(indent_change_before) %} + <ul class="unstyled"> + {% endfor %} + <li><a class="reference badge" href="{{ link }}">{{ text }}</a> + {% if indent_change_after <= 0 %} + </li> {% endif %} + {% for i in range(-indent_change_after) %} + </ul> + {% if i + 1 < indent_levels|length %} + </li> + {% endif %} + {% endfor %} {% endfor %} - </ul> {% if items %} <h2>{{ messages("Tags") }}</h2> {% endif %} @@ -19,7 +29,9 @@ {% if items %} <ul class="list-inline"> {% for text, link in items %} - <li><a class="reference badge" href="{{ link }}">{{ text }}</a></li> + {% if text not in hidden_tags %} + <li><a class="reference badge" href="{{ link }}">{{ text }}</a></li> + {% endif %} {% endfor %} </ul> {% endif %} diff --git a/nikola/data/themes/bootstrap/README.md b/nikola/data/themes/bootstrap/README.md index 5340fe2..637caf5 100644 --- a/nikola/data/themes/bootstrap/README.md +++ b/nikola/data/themes/bootstrap/README.md @@ -3,7 +3,7 @@ A "website-done-with-bootstrap" theme, so to speak. Has a fixed navigation bar at top that displays the NAVIGATION_LINKS setting and supports nested menus. -This theme is used in Nikola's website: http://getnikola.com +This theme is used in Nikola's website: https://getnikola.com Important: To fit in the bootstrap navigation bar, the search form needs the navbar-form and pull-left CSS classes applied. Here is an example with Nikola's diff --git a/nikola/data/themes/bootstrap/assets/css/theme.css b/nikola/data/themes/bootstrap/assets/css/theme.css index 761dbb6..4fc31a8 100644 --- a/nikola/data/themes/bootstrap/assets/css/theme.css +++ b/nikola/data/themes/bootstrap/assets/css/theme.css @@ -1,11 +1,3 @@ -body { - padding-top: 60px; -} -@media (max-width: 979px) { - body { - padding-top: 0px; - } -} #container { width: 960px; margin: 50 auto; @@ -91,17 +83,6 @@ article.post-micro { font-size: 1.5em; } -/* fix anchors for headers */ -h1, h2, h3 { - margin-top: -40px; - padding-top: 60px; -} - -h4, h5, h6 { - margin-top: -50px; - padding-top: 60px; -} - .image-block { display: inline-block; } @@ -193,3 +174,32 @@ h4, h5, h6 { overflow: visible; clip: auto; } + +/* hat tip bootstrap/html5 boilerplate */ +@media print { + *, *:before, *:after { + font-family: Garamond, Junicode, serif; + } + + body { + font-size: 12pt; + } + + article .entry-title a[href]:after, + article .metadata a[href]:after, + article .tags a[href]:after { + content: ""; + } + + article .metadata .sourceline { + display: none; + } + + article .metadata .linkline a[href]:after { + content: " (" attr(href) ")"; + } + + .navbar { + display: none; + } +} diff --git a/nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-bn.js b/nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-bn.js new file mode 120000 index 0000000..9b995d8 --- /dev/null +++ b/nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-bn.js @@ -0,0 +1 @@ +../../../../../../../bower_components/jquery-colorbox/i18n/jquery.colorbox-bn.js
\ No newline at end of file diff --git a/nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-pt-BR.js b/nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-pt-BR.js new file mode 120000 index 0000000..e20bd38 --- /dev/null +++ b/nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-pt-BR.js @@ -0,0 +1 @@ +../../../../../../../bower_components/jquery-colorbox/i18n/jquery.colorbox-pt-BR.js
\ No newline at end of file diff --git a/nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-pt-br.js b/nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-pt-br.js deleted file mode 120000 index 76f289e..0000000 --- a/nikola/data/themes/bootstrap/assets/js/colorbox-i18n/jquery.colorbox-pt-br.js +++ /dev/null @@ -1 +0,0 @@ -../../../../../../../bower_components/jquery-colorbox/i18n/jquery.colorbox-pt-br.js
\ No newline at end of file diff --git a/nikola/data/themes/bootstrap/assets/js/jquery.js b/nikola/data/themes/bootstrap/assets/js/jquery.js new file mode 120000 index 0000000..966173b --- /dev/null +++ b/nikola/data/themes/bootstrap/assets/js/jquery.js @@ -0,0 +1 @@ +../../../../../../bower_components/jquery/dist/jquery.js
\ No newline at end of file diff --git a/nikola/data/themes/bootstrap/bundles b/nikola/data/themes/bootstrap/bundles index 089b036..38257d2 100644 --- a/nikola/data/themes/bootstrap/bundles +++ b/nikola/data/themes/bootstrap/bundles @@ -1,4 +1,4 @@ assets/css/all-nocdn.css=bootstrap.css,bootstrap-responsive.css,rst.css,code.css,colorbox.css,theme.css,custom.css assets/css/all.css=rst.css,code.css,colorbox.css,theme.css,custom.css -assets/js/all-nocdn.js=jquery.min.js,bootstrap.min.js,jquery.colorbox-min.js -assets/js/all.js=jquery.colorbox-min.js +assets/js/all-nocdn.js=jquery.min.js,bootstrap.min.js,jquery.colorbox-min.js,moment-with-locales.min.js,fancydates.js +assets/js/all.js=jquery.colorbox-min.js,moment-with-locales.min.js,fancydates.js diff --git a/nikola/data/themes/bootstrap/templates/base.tmpl b/nikola/data/themes/bootstrap/templates/base.tmpl index 9f2bb61..e848673 100644 --- a/nikola/data/themes/bootstrap/templates/base.tmpl +++ b/nikola/data/themes/bootstrap/templates/base.tmpl @@ -13,7 +13,7 @@ ${template_hooks['extra_head']()} <!-- Menubar --> -<div class="navbar navbar-fixed-top" id="navbar"> +<div class="navbar navbar-static-top" id="navbar"> <div class="navbar-inner"> <div class="container"> @@ -24,7 +24,7 @@ ${template_hooks['extra_head']()} <span class="icon-bar"></span> </a> - <a class="brand" href="${abs_link('/')}"> + <a class="brand" href="${abs_link(_link("root", None, lang))}"> %if logo_url: <img src="${logo_url}" alt="${blog_title}" id="logo"> %endif @@ -58,7 +58,7 @@ ${template_hooks['extra_head']()} </div> </div> <!-- End of Menubar --> -<div class="container-fluid" id="content"> +<div class="container-fluid" id="content" role="main"> <!--Body content--> <div class="row-fluid"> <div class="span2"></div> @@ -74,7 +74,13 @@ ${template_hooks['extra_head']()} ${template_hooks['page_footer']()} </div> ${base.late_load_js()} - <script>jQuery("a.image-reference").colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});</script> + <script>$('a.image-reference:not(.islink) img:not(.islink)').parent().colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});</script> + <!-- fancy dates --> + <script> + moment.locale("${momentjs_locales[lang]}"); + fancydates(${date_fanciness}, ${js_date_format}); + </script> + <!-- end fancy dates --> <%block name="extra_js"></%block> % if annotations and post and not post.meta('noannotations'): ${notes.code()} diff --git a/nikola/data/themes/bootstrap/templates/base_helper.tmpl b/nikola/data/themes/bootstrap/templates/base_helper.tmpl index 40cce39..4c62f8d 100644 --- a/nikola/data/themes/bootstrap/templates/base_helper.tmpl +++ b/nikola/data/themes/bootstrap/templates/base_helper.tmpl @@ -1,5 +1,6 @@ ## -*- coding: utf-8 -*- +<%namespace name="notes" file="annotation_helper.tmpl" import="*" /> <%def name="html_headstart()"> <!DOCTYPE html> <html @@ -68,19 +69,21 @@ lang="${lang}"> <%def name="late_load_js()"> %if use_bundles: %if use_cdn: - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> - <script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> + <script src="//maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script> <script src="/assets/js/all.js"></script> %else: <script src="/assets/js/all-nocdn.js"></script> %endif %else: %if use_cdn: - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> - <script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> + <script src="//maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/js/bootstrap.min.js"></script> %else: <script src="/assets/js/jquery.min.js"></script> <script src="/assets/js/bootstrap.min.js"></script> + <script src="/assets/js/moment-with-locales.min.js"></script> + <script src="/assets/js/fancydates.js"></script> %endif <script src="/assets/js/jquery.colorbox-min.js"></script> %endif @@ -94,14 +97,14 @@ lang="${lang}"> <%def name="html_stylesheets()"> %if use_bundles: %if use_cdn: - <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet"> + <link href="//maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet"> <link href="/assets/css/all.css" rel="stylesheet" type="text/css"> %else: <link href="/assets/css/all-nocdn.css" rel="stylesheet" type="text/css"> %endif %else: %if use_cdn: - <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet"> + <link href="//maxcdn.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet"> %else: <link href="/assets/css/bootstrap.min.css" rel="stylesheet" type="text/css"> <link href="/assets/css/bootstrap-responsive.min.css" rel="stylesheet" type="text/css"> @@ -114,6 +117,10 @@ lang="${lang}"> <link href="/assets/css/custom.css" rel="stylesheet" type="text/css"> %endif %endif + % if needs_ipython_css: + <link href="/assets/css/ipython.min.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/nikola_ipython.css" rel="stylesheet" type="text/css"> + % endif % if annotations and post and not post.meta('noannotations'): ${notes.css()} % elif not annotations and post and post.meta('annotations'): @@ -129,7 +136,7 @@ lang="${lang}"> <ul class="dropdown-menu"> %for suburl, text in url: % if rel_link(permalink, suburl) == "#": - <li class="active"><a href="${permalink}">${text}</a> + <li class="active"><a href="${permalink}">${text} <span class="sr-only">${messages("(active)", lang)}</span></a> %else: <li><a href="${suburl}">${text}</a> %endif @@ -137,7 +144,7 @@ lang="${lang}"> </ul> % else: % if rel_link(permalink, url) == "#": - <li class="active"><a href="${permalink}">${text}</a> + <li class="active"><a href="${permalink}">${text} <span class="sr-only">${messages("(active)", lang)}</span></a> %else: <li><a href="${url}">${text}</a> %endif @@ -157,12 +164,21 @@ lang="${lang}"> <link rel="alternate" type="application/rss+xml" title="RSS" href="${_link('rss', None)}"> %endif %endif + %if generate_atom: + %if len(translations) > 1: + %for language in translations: + <link rel="alternate" type="application/atom+xml" title="Atom (${language})" href="${_link('index_atom', None, language)}"> + %endfor + %else: + <link rel="alternate" type="application/atom+xml" title="Atom" href="${_link('index_atom', None)}"> + %endif + %endif </%def> <%def name="html_translations()"> %for langname in translations.keys(): %if langname != lang: - <li><a href="${_link("index", None, langname)}" rel="alternate" hreflang="${langname}">${messages("LANGUAGE", langname)}</a></li> + <li><a href="${abs_link(_link("root", None, langname))}" rel="alternate" hreflang="${langname}">${messages("LANGUAGE", langname)}</a></li> %endif %endfor </%def> diff --git a/nikola/data/themes/bootstrap/templates/gallery.tmpl b/nikola/data/themes/bootstrap/templates/gallery.tmpl index 8ad4eb4..ab15587 100644 --- a/nikola/data/themes/bootstrap/templates/gallery.tmpl +++ b/nikola/data/themes/bootstrap/templates/gallery.tmpl @@ -7,7 +7,7 @@ <%block name="content"> ${ui.bar(crumbs)} %if title: - <h1>${title}</h1> + <h1>${title|h}</h1> %endif %if post: <p> @@ -40,6 +40,7 @@ ${comments.comment_form(None, permalink, title)} <%block name="extra_head"> ${parent.extra_head()} +<link rel="alternate" type="application/rss+xml" title="RSS" href="rss.xml"> <style type="text/css"> .image-block { display: inline-block; diff --git a/nikola/data/themes/bootstrap/templates/post.tmpl b/nikola/data/themes/bootstrap/templates/post.tmpl index e55fcd5..8d9f88a 100644 --- a/nikola/data/themes/bootstrap/templates/post.tmpl +++ b/nikola/data/themes/bootstrap/templates/post.tmpl @@ -14,11 +14,14 @@ %endif <meta name="author" content="${post.author()}"> %if post.prev_post: - <link rel="prev" href="${post.prev_post.permalink()}" title="${post.prev_post.title()}" type="text/html"> + <link rel="prev" href="${post.prev_post.permalink()}" title="${post.prev_post.title()|h}" type="text/html"> %endif %if post.next_post: - <link rel="next" href="${post.next_post.permalink()}" title="${post.next_post.title()}" type="text/html"> + <link rel="next" href="${post.next_post.permalink()}" title="${post.next_post.title()|h}" type="text/html"> %endif + % if post.is_draft: + <meta name="robots" content="noindex"> + % endif ${helper.open_graph_metadata(post)} ${helper.twitter_card_information(post)} ${helper.meta_translations(post)} @@ -37,7 +40,7 @@ </nav> </aside> % if not post.meta('nocomments') and site_has_comments: - <section class="comments"> + <section class="comments hidden-print"> <h2>${messages("Comments")}</h2> ${comments.comment_form(post.permalink(absolute=True), post.title(), post._base_path)} </section> diff --git a/nikola/data/themes/bootstrap/templates/tags.tmpl b/nikola/data/themes/bootstrap/templates/tags.tmpl index 9afeca7..ead3b0a 100644 --- a/nikola/data/themes/bootstrap/templates/tags.tmpl +++ b/nikola/data/themes/bootstrap/templates/tags.tmpl @@ -4,14 +4,24 @@ <%block name="content"> <h1>${title}</h1> % if cat_items: - <h2>${messages("Categories")}</h2> - <ul class="unstyled"> - % for text, link in cat_items: - % if text: - <li><a class="reference badge" href="${link}">${text}</a></li> + % if items: + <h2>${messages("Categories")}</h2> + % endif + % for text, full_name, path, link, indent_levels, indent_change_before, indent_change_after in cat_hierarchy: + % for i in range(indent_change_before): + <ul class="unstyled"> + % endfor + <li><a class="reference badge" href="${link}">${text}</a> + % if indent_change_after <= 0: + </li> % endif + % for i in range(-indent_change_after): + </ul> + % if i + 1 < len(indent_levels): + </li> + % endif + % endfor % endfor - </ul> % if items: <h2>${messages("Tags")}</h2> % endif @@ -19,7 +29,9 @@ % if items: <ul class="list-inline"> % for text, link in items: - <li><a class="reference badge" href="${link}">${text}</a></li> + % if text not in hidden_tags: + <li><a class="reference badge" href="${link}">${text}</a></li> + % endif % endfor </ul> % endif diff --git a/nikola/data/themes/bootstrap3-jinja/assets/css/docs.css b/nikola/data/themes/bootstrap3-jinja/assets/css/docs.css index b9cce36..189ea89 120000..100644 --- a/nikola/data/themes/bootstrap3-jinja/assets/css/docs.css +++ b/nikola/data/themes/bootstrap3-jinja/assets/css/docs.css @@ -1 +1,160 @@ -../../../bootstrap3/assets/css/docs.css
\ No newline at end of file +body { + font-weight: 300; +} + +a:hover, +a:focus { + text-decoration: none; +} + +.container { + max-width: 700px; +} + +h2 { + text-align: center; + font-weight: 300; +} + + +/* Header +-------------------------------------------------- */ + +.jumbotron { + position: relative; + font-size: 16px; + color: #fff; + color: rgba(255,255,255,.75); + text-align: center; + background-color: #b94a48; + border-radius: 0; +} +.jumbotron h1, +.jumbotron .glyphicon-ok { + margin-bottom: 15px; + font-weight: 300; + letter-spacing: -1px; + color: #fff; +} +.jumbotron .glyphicon-ok { + font-size: 40px; + line-height: 1; +} +.btn-outline { + margin-top: 15px; + margin-bottom: 15px; + padding: 18px 24px; + font-size: inherit; + font-weight: 500; + color: #fff; /* redeclare to override the `.jumbotron a` */ + background-color: transparent; + border-color: #fff; + border-color: rgba(255,255,255,.5); + transition: all .1s ease-in-out; +} +.btn-outline:hover, +.btn-outline:active { + color: #b94a48; + background-color: #fff; + border-color: #fff; +} + +.jumbotron:after { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 10; + display: block; + content: ""; + height: 30px; + background-image: -moz-linear-gradient(rgba(0, 0, 0, 0), rgba(0,0,0,.1)); + background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0), rgba(0,0,0,.1)); +} + +.jumbotron p a, +.jumbotron-links a { + font-weight: 500; + color: #fff; + transition: all .1s ease-in-out; +} +.jumbotron p a:hover, +.jumbotron-links a:hover { + text-shadow: 0 0 10px rgba(255,255,255,.55); +} + +/* Textual links */ +.jumbotron-links { + margin-top: 15px; + margin-bottom: 0; + padding-left: 0; + list-style: none; + font-size: 14px; +} +.jumbotron-links li { + display: inline; +} +.jumbotron-links li + li { + margin-left: 20px; +} + +@media (min-width: 768px) { + .jumbotron { + padding-top: 100px; + padding-bottom: 100px; + font-size: 21px; + } + .jumbotron h1, + .jumbotron .glyphicon-ok { + font-size: 50px; + } +} + +/* Steps for setup +-------------------------------------------------- */ + +.how-to { + padding: 50px 20px; + border-top: 1px solid #eee; +} +.how-to li { + font-size: 21px; + line-height: 1.5; + margin-top: 20px; +} +.how-to li p { + font-size: 16px; + color: #555; +} +.how-to code { + font-size: 85%; + color: #b94a48; + background-color: #fcf3f2; + word-wrap: break-word; + white-space: normal; +} + +/* Icons +-------------------------------------------------- */ + +.the-icons { + padding: 40px 10px; + font-size: 20px; + line-height: 2; + color: #333; + text-align: center; +} +.the-icons .glyphicon { + padding-left: 15px; + padding-right: 15px; +} + +/* Footer +-------------------------------------------------- */ + +.footer { + padding: 50px 30px; + color: #777; + text-align: center; + border-top: 1px solid #eee; +} diff --git a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomCenter.png b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomCenter.png Binary files differindex 2a6267e..0d4475e 120000..100644 --- a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomCenter.png +++ b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomCenter.png diff --git a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomLeft.png b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomLeft.png Binary files differindex 6cd025a..2775eba 120000..100644 --- a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomLeft.png +++ b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomLeft.png diff --git a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomRight.png b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomRight.png Binary files differindex 9596518..f7f5137 120000..100644 --- a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomRight.png +++ b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderBottomRight.png diff --git a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderMiddleLeft.png b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderMiddleLeft.png Binary files differindex b5403bf..a2d63d1 120000..100644 --- a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderMiddleLeft.png +++ b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderMiddleLeft.png diff --git a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderMiddleRight.png b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderMiddleRight.png Binary files differindex 27c023f..fd7c3e8 120000..100644 --- a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderMiddleRight.png +++ b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderMiddleRight.png diff --git a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopCenter.png b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopCenter.png Binary files differindex e272a45..2937a9c 120000..100644 --- a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopCenter.png +++ b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopCenter.png diff --git a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopLeft.png b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopLeft.png Binary files differindex e8ceae5..f9d458b 120000..100644 --- a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopLeft.png +++ b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopLeft.png diff --git a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopRight.png b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopRight.png Binary files differindex 9a84403..74b8583 120000..100644 --- a/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopRight.png +++ b/nikola/data/themes/bootstrap3-jinja/assets/css/images/ie6/borderTopRight.png diff --git a/nikola/data/themes/bootstrap3-jinja/assets/css/rst.css b/nikola/data/themes/bootstrap3-jinja/assets/css/rst.css deleted file mode 120000 index d78763e..0000000 --- a/nikola/data/themes/bootstrap3-jinja/assets/css/rst.css +++ /dev/null @@ -1 +0,0 @@ -../../../bootstrap3/assets/css/rst.css
\ No newline at end of file diff --git a/nikola/data/themes/bootstrap3-jinja/assets/css/theme.css b/nikola/data/themes/bootstrap3-jinja/assets/css/theme.css index a2774ff..9ce6472 120000..100644 --- a/nikola/data/themes/bootstrap3-jinja/assets/css/theme.css +++ b/nikola/data/themes/bootstrap3-jinja/assets/css/theme.css @@ -1 +1,213 @@ -../../../bootstrap3/assets/css/theme.css
\ No newline at end of file +#container { + width: 960px; + margin: 0 auto; +} + +#contentcolumn { + max-width: 760px; +} +#q { + width: 150px; +} + +img { + max-width: 90%; +} + +.postbox { + border-bottom: 2px solid darkgrey; + margin-bottom: 12px; +} + +.titlebox { + text-align: right; +} + +#addthisbox {margin-bottom: 12px;} + +td.label { + /* Issue #290 */ + background-color: inherit; +} + +.footnote-reference { + /* Issue 290 */ + vertical-align: super; + font-size: xx-small; +} + + +.caption { + /* Issue 292 */ + text-align: center; + padding-top: 1em; +} + +div.figure > img, +div.figure > a > img { + /* Issue 292 */ + display: block; + margin-left: auto; + margin-right: auto; +} + +div.sidebar, div.admonition, div.attention, div.caution, div.danger, div.error, div.hint, div.important, div.note, div.tip, div.warning { + /* Issue 277 */ + border: 1px solid #aaa; + border-radius: 5px; +} + +blockquote p, blockquote { + font-size: 17.5px; + font-weight: 300; + line-height: 1.25; +} + +ul.bricks > li { + display: inline; + background-color: lightblue; + padding: 8px; + border-radius: 5px; + line-height: 3; + white-space:nowrap; + margin: 3px; +} + +.at300b, .stMainServices, .stButton, .stButton_gradient { + box-sizing: content-box; +} + +pre, pre code { + white-space: pre; + word-wrap: normal; + overflow: auto; +} + +article.post-micro { + font-family: Georgia, 'Times New Roman', Times, serif; + font-size: 1.5em; +} + +.image-block { + display: inline-block; +} + +.flowr_row { + width: 100%; +} + +.tags { + padding-left: 0; + margin-left: -5px; + list-style: none; + text-align: center; + +} + +.tags > li { + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #999; + border-radius: 10px; +} + +.tags > li a { + color: #fff; +} + +.metadata p:before, +.postlist .listdate:before { + content: " — "; +} + +.metadata p:first-of-type:before { + content: ""; +} + +.metadata p { + display: inline; +} + +.posttranslations h3 { + display: inline; + font-size: 1em; + font-weight: bold; +} + +.posttranslations h3:last-child { + display: none; +} + +.entry-content { + margin-top: 1em; +} + +.navbar-brand { + padding: 0 15px; +} + +.navbar-brand #blog-title { + padding: 15px 0; + display: inline-block; +} + +.navbar-brand #logo { + max-width: 100%; +} + +.navbar-brand>img { + display: inline; +} + +.row { + margin: 0; +} + +/* for alignment with Bootstrap's .entry-content styling */ +.entry-summary { + margin-top: 1em; +} + +/* Custom page footer */ +#footer { + padding-top: 19px; + color: #777; + border-top: 1px solid #e5e5e5; +} + +/* hat tip bootstrap/html5 boilerplate */ +@media print { + *, *:before, *:after { + font-family: Garamond, Junicode, serif; + } + + body { + font-size: 12pt; + } + + article .entry-title a[href]:after, + article .metadata a[href]:after, + article .tags a[href]:after { + content: ""; + } + + article .metadata .sourceline { + display: none; + } + + article .metadata .linkline a[href]:after { + content: " (" attr(href) ")"; + } + + .navbar { + display: none; + } +} diff --git a/nikola/data/themes/bootstrap3-jinja/assets/fonts/glyphicons-halflings-regular.woff2 b/nikola/data/themes/bootstrap3-jinja/assets/fonts/glyphicons-halflings-regular.woff2 new file mode 120000 index 0000000..8c1e4d3 --- /dev/null +++ b/nikola/data/themes/bootstrap3-jinja/assets/fonts/glyphicons-halflings-regular.woff2 @@ -0,0 +1 @@ +../../../../../../bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2
\ No newline at end of file diff --git a/nikola/data/themes/bootstrap3-jinja/templates/base.tmpl b/nikola/data/themes/bootstrap3-jinja/templates/base.tmpl index c1ac838..058640a 100644 --- a/nikola/data/themes/bootstrap3-jinja/templates/base.tmpl +++ b/nikola/data/themes/bootstrap3-jinja/templates/base.tmpl @@ -13,7 +13,7 @@ <!-- Menubar --> -<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> +<nav class="navbar navbar-inverse navbar-static-top" role="navigation"> <div class="container"><!-- This keeps the margins nice --> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> @@ -22,7 +22,7 @@ <span class="icon-bar"></span> <span class="icon-bar"></span> </button> - <a class="navbar-brand" href="{{ abs_link('/') }}"> + <a class="navbar-brand" href="{{ abs_link(_link("root", None, lang)) }}"> {% if logo_url %} <img src="{{ logo_url }}" alt="{{ blog_title }}" id="logo"> {% endif %} @@ -58,7 +58,7 @@ <!-- End of Menubar --> -<div class="container" id="content"> +<div class="container" id="content" role="main"> <div class="body-content"> <!--Body content--> <div class="row"> @@ -67,7 +67,7 @@ </div> <!--End of body content--> - <footer> + <footer id="footer"> {{ content_footer }} {{ template_hooks['page_footer']() }} </footer> @@ -75,7 +75,13 @@ </div> {{ base.late_load_js() }} - <script>jQuery("a.image-reference").colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});</script> + <script>$('a.image-reference:not(.islink) img:not(.islink)').parent().colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});</script> + <!-- fancy dates --> + <script> + moment.locale("{{ momentjs_locales[lang] }}"); + fancydates({{ date_fanciness }}, {{ js_date_format }}); + </script> + <!-- end fancy dates --> {% block extra_js %}{% endblock %} {% if annotations and post and not post.meta('noannotations') %} {{ notes.code() }} diff --git a/nikola/data/themes/bootstrap3-jinja/templates/base_helper.tmpl b/nikola/data/themes/bootstrap3-jinja/templates/base_helper.tmpl index 38a73c4..a481632 100644 --- a/nikola/data/themes/bootstrap3-jinja/templates/base_helper.tmpl +++ b/nikola/data/themes/bootstrap3-jinja/templates/base_helper.tmpl @@ -1,5 +1,6 @@ {# -*- coding: utf-8 -*- #} +{% import 'annotation_helper.tmpl' as notes with context %} {% macro html_headstart() %} <!DOCTYPE html> <html @@ -67,19 +68,21 @@ lang="{{ lang }}"> {% macro late_load_js() %} {% if use_bundles %} {% if use_cdn %} - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> - <script src="//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> + <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> <script src="/assets/js/all.js"></script> {% else %} <script src="/assets/js/all-nocdn.js"></script> {% endif %} {% else %} {% if use_cdn %} - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> - <script src="//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> + <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> {% else %} <script src="/assets/js/jquery.min.js"></script> <script src="/assets/js/bootstrap.min.js"></script> + <script src="/assets/js/moment-with-locales.min.js"></script> + <script src="/assets/js/fancydates.js"></script> {% endif %} <script src="/assets/js/jquery.colorbox-min.js"></script> {% endif %} @@ -93,14 +96,14 @@ lang="{{ lang }}"> {% macro html_stylesheets() %} {% if use_bundles %} {% if use_cdn %} - <link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"> + <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"> <link href="/assets/css/all.css" rel="stylesheet" type="text/css"> {% else %} <link href="/assets/css/all-nocdn.css" rel="stylesheet" type="text/css"> {% endif %} {% else %} {% if use_cdn %} - <link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"> + <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"> {% else %} <link href="/assets/css/bootstrap.min.css" rel="stylesheet" type="text/css"> {% endif %} @@ -112,6 +115,10 @@ lang="{{ lang }}"> <link href="/assets/css/custom.css" rel="stylesheet" type="text/css"> {% endif %} {% endif %} + {% if needs_ipython_css %} + <link href="/assets/css/ipython.min.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/nikola_ipython.css" rel="stylesheet" type="text/css"> + {% endif %} {% if annotations and post and not post.meta('noannotations') %} {{ notes.css() }} {% elif not annotations and post and post.meta('annotations') %} @@ -122,11 +129,11 @@ lang="{{ lang }}"> {% macro html_navigation_links() %} {% for url, text in navigation_links[lang] %} {% if isinstance(url, tuple) %} - <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ text }}<b class="caret"></b></a> + <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ text }} <b class="caret"></b></a> <ul class="dropdown-menu"> {% for suburl, text in url %} {% if rel_link(permalink, suburl) == "#" %} - <li class="active"><a href="{{ permalink }}">{{ text }}</a> + <li class="active"><a href="{{ permalink }}">{{ text }} <span class="sr-only">{{ messages("(active)", lang) }}</span></a> {% else %} <li><a href="{{ suburl }}">{{ text }}</a> {% endif %} @@ -134,7 +141,7 @@ lang="{{ lang }}"> </ul> {% else %} {% if rel_link(permalink, url) == "#" %} - <li class="active"><a href="{{ permalink }}">{{ text }}</a> + <li class="active"><a href="{{ permalink }}">{{ text }} <span class="sr-only">{{ messages("(active)", lang) }}</span></a> {% else %} <li><a href="{{ url }}">{{ text }}</a> {% endif %} @@ -154,12 +161,21 @@ lang="{{ lang }}"> <link rel="alternate" type="application/rss+xml" title="RSS" href="{{ _link('rss', None) }}"> {% endif %} {% endif %} + {% if generate_atom %} + {% if translations|length > 1 %} + {% for language in translations %} + <link rel="alternate" type="application/atom+xml" title="Atom ({{ language }})" href="{{ _link('index_atom', None, language) }}"> + {% endfor %} + {% else %} + <link rel="alternate" type="application/atom+xml" title="Atom" href="{{ _link('index_atom', None) }}"> + {% endif %} + {% endif %} {% endmacro %} {% macro html_translations() %} {% for langname in translations.keys() %} {% if langname != lang %} - <li><a href="{{ _link("index", None, langname) }}" rel="alternate" hreflang="{{ langname }}">{{ messages("LANGUAGE", langname) }}</a></li> + <li><a href="{{ abs_link(_link("root", None, langname)) }}" rel="alternate" hreflang="{{ langname }}">{{ messages("LANGUAGE", langname) }}</a></li> {% endif %} {% endfor %} {% endmacro %} diff --git a/nikola/data/themes/bootstrap3-jinja/templates/gallery.tmpl b/nikola/data/themes/bootstrap3-jinja/templates/gallery.tmpl index 11382c3..00fda11 100644 --- a/nikola/data/themes/bootstrap3-jinja/templates/gallery.tmpl +++ b/nikola/data/themes/bootstrap3-jinja/templates/gallery.tmpl @@ -7,7 +7,7 @@ {% block content %} {{ ui.bar(crumbs) }} {% if title %} - <h1>{{ title }}</h1> + <h1>{{ title|e }}</h1> {% endif %} {% if post %} <p> @@ -17,8 +17,7 @@ {% if folders %} <ul> {% for folder, ftitle in folders %} - <li><a href="{{ folder }}"><i class="glyphicon - glyphicon-folder-open"></i> {{ ftitle }}</a></li> + <li><a href="{{ folder }}"><i class="glyphicon glyphicon-folder-open"></i> {{ ftitle }}</a></li> {% endfor %} </ul> {% endif %} @@ -41,6 +40,7 @@ {% block extra_head %} {{ super() }} +<link rel="alternate" type="application/rss+xml" title="RSS" href="rss.xml"> <style type="text/css"> .image-block { display: inline-block; diff --git a/nikola/data/themes/bootstrap3/assets/css/rst.css b/nikola/data/themes/bootstrap3/assets/css/rst.css deleted file mode 100644 index 489ceaa..0000000 --- a/nikola/data/themes/bootstrap3/assets/css/rst.css +++ /dev/null @@ -1,318 +0,0 @@ -/* -:Author: David Goodger (goodger@python.org) -:Id: $Id: html4css1.css 7514 2012-09-14 14:27:12Z milde $ -:Copyright: This stylesheet has been placed in the public domain. - -Default cascading style sheet for the HTML output of Docutils. - -See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to -customize this style sheet. -*/ - -/* used to remove borders from tables and images */ -.borderless, table.borderless td, table.borderless th { - border: 0 } - -table.borderless td, table.borderless th { - /* Override padding for "table.docutils td" with "! important". - The right padding separates the table cells. */ - padding: 0 0.5em 0 0 ! important } - -.first { - /* Override more specific margin styles with "! important". */ - margin-top: 0 ! important } - -.last, .with-subtitle { - margin-bottom: 0 ! important } - -.hidden { - display: none } - -a.toc-backref { - text-decoration: none ; - color: black } - -blockquote.epigraph { - margin: 2em 5em ; } - -dl.docutils dd { - margin-bottom: 0.5em } - -object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] { - overflow: hidden; -} - -/* Uncomment (and remove this text!) to get bold-faced definition list terms -dl.docutils dt { - font-weight: bold } -*/ - -div.abstract { - margin: 2em 5em } - -div.abstract p.topic-title { - font-weight: bold ; - text-align: center } - -div.admonition, div.attention, div.caution, div.danger, div.error, -div.hint, div.important, div.note, div.tip, div.warning { - margin: 2em ; - border: medium outset ; - padding: 1em } - -div.admonition p.admonition-title, div.hint p.admonition-title, -div.important p.admonition-title, div.note p.admonition-title, -div.tip p.admonition-title { - font-weight: bold ; - font-family: sans-serif } - -div.attention p.admonition-title, div.caution p.admonition-title, -div.danger p.admonition-title, div.error p.admonition-title, -div.warning p.admonition-title, .code .error { - color: red ; - font-weight: bold ; - font-family: sans-serif } - -/* Uncomment (and remove this text!) to get reduced vertical space in - compound paragraphs. -div.compound .compound-first, div.compound .compound-middle { - margin-bottom: 0.5em } - -div.compound .compound-last, div.compound .compound-middle { - margin-top: 0.5em } -*/ - -div.dedication { - margin: 2em 5em ; - text-align: center ; - font-style: italic } - -div.dedication p.topic-title { - font-weight: bold ; - font-style: normal } - -div.figure { - margin-left: 2em ; - margin-right: 2em } - -div.footer, div.header { - clear: both; - font-size: smaller } - -div.line-block { - display: block ; - margin-top: 1em ; - margin-bottom: 1em } - -div.line-block div.line-block { - margin-top: 0 ; - margin-bottom: 0 ; - margin-left: 1.5em } - -html[dir="rtl"] div.line-block div.line-block { - margin-top: 0 ; - margin-bottom: 0 ; - margin-right: 1.5em ; - margin-left: 0 } - -div.sidebar { - margin: 0 0 0.5em 1em ; - border: medium outset ; - padding: 1em ; - background-color: #ffffee ; - width: 40% ; - float: right ; - clear: right } - -div.sidebar p.rubric { - font-family: sans-serif ; - font-size: medium } - -div.system-messages { - margin: 5em } - -div.system-messages h1 { - color: red } - -div.system-message { - border: medium outset ; - padding: 1em } - -div.system-message p.system-message-title { - color: red ; - font-weight: bold } - -div.topic { - margin: 2em } - -h1.section-subtitle, h2.section-subtitle, h3.section-subtitle, -h4.section-subtitle, h5.section-subtitle, h6.section-subtitle { - margin-top: 0.4em } - -h1.title { - text-align: center } - -h2.subtitle { - text-align: center } - -hr.docutils { - width: 75% } - -img.align-left, .figure.align-left, object.align-left { - clear: left ; - float: left ; - margin-right: 1em } - -img.align-right, .figure.align-right, object.align-right { - clear: right ; - float: right ; - margin-left: 1em } - -img.align-center, .figure.align-center, object.align-center { - display: block; - margin-left: auto; - margin-right: auto; -} - -.align-left { - text-align: left } - -.align-center { - clear: both ; - text-align: center } - -.align-right { - text-align: right } - -/* reset inner alignment in figures */ -div.align-right { - text-align: inherit } - -/* div.align-center * { */ -/* text-align: left } */ - -ol.simple, ul.simple { - margin-bottom: 1em } - -ol.arabic { - list-style: decimal } - -ol.loweralpha { - list-style: lower-alpha } - -ol.upperalpha { - list-style: upper-alpha } - -ol.lowerroman { - list-style: lower-roman } - -ol.upperroman { - list-style: upper-roman } - -p.attribution { - text-align: right ; - margin-left: 50% } - -p.caption { - font-style: italic } - -p.credits { - font-style: italic ; - font-size: smaller } - -p.label { - white-space: nowrap } - -p.rubric { - font-weight: bold ; - font-size: larger ; - color: maroon ; - text-align: center } - -p.sidebar-title { - font-family: sans-serif ; - font-weight: bold ; - font-size: larger } - -p.sidebar-subtitle { - font-family: sans-serif ; - font-weight: bold } - -p.topic-title { - font-weight: bold } - -pre.address { - margin-bottom: 0 ; - margin-top: 0 ; - font: inherit } - -pre.literal-block, pre.doctest-block, pre.math, pre.code { - margin-left: 2em ; - margin-right: 2em } - -pre.code .ln { color: grey; } /* line numbers */ -pre.code, code { background-color: #eeeeee } -pre.code .comment, code .comment { color: #5C6576 } -pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold } -pre.code .literal.string, code .literal.string { color: #0C5404 } -pre.code .name.builtin, code .name.builtin { color: #352B84 } -pre.code .deleted, code .deleted { background-color: #DEB0A1} -pre.code .inserted, code .inserted { background-color: #A3D289} - -span.classifier { - font-family: sans-serif ; - font-style: oblique } - -span.classifier-delimiter { - font-family: sans-serif ; - font-weight: bold } - -span.interpreted { - font-family: sans-serif } - -span.option { - white-space: nowrap } - -span.pre { - white-space: pre } - -span.problematic { - color: red } - -span.section-subtitle { - /* font-size relative to parent (h1..h6 element) */ - font-size: 80% } - -table.citation { - border-left: solid 1px gray; - margin-left: 1px } - -table.docinfo { - margin: 2em 4em } - -table.docutils { - margin-top: 0.5em ; - margin-bottom: 0.5em } - -table.footnote { - border-left: solid 1px black; - margin-left: 1px } - -table.docutils td, table.docutils th, -table.docinfo td, table.docinfo th { - padding-left: 0.5em ; - padding-right: 0.5em ; - vertical-align: top } - -table.docutils th.field-name, table.docinfo th.docinfo-name { - font-weight: bold ; - text-align: left ; - white-space: nowrap ; - padding-left: 0 } - -h1 tt.docutils, h2 tt.docutils, h3 tt.docutils, -h4 tt.docutils, h5 tt.docutils, h6 tt.docutils { - font-size: 100% } - -ul.auto-toc { - list-style-type: none } diff --git a/nikola/data/themes/bootstrap3/assets/css/theme.css b/nikola/data/themes/bootstrap3/assets/css/theme.css index 5e3775a..9ce6472 100644 --- a/nikola/data/themes/bootstrap3/assets/css/theme.css +++ b/nikola/data/themes/bootstrap3/assets/css/theme.css @@ -1,7 +1,3 @@ -body { - margin-top: 60px; -} - #container { width: 960px; margin: 0 auto; @@ -92,17 +88,6 @@ article.post-micro { font-size: 1.5em; } -/* fix anchors for headers */ -h1, h2, h3 { - margin-top: -40px; - padding-top: 60px; -} - -h4, h5, h6 { - margin-top: -50px; - padding-top: 60px; -} - .image-block { display: inline-block; } @@ -178,6 +163,51 @@ h4, h5, h6 { max-width: 100%; } +.navbar-brand>img { + display: inline; +} + .row { margin: 0; } + +/* for alignment with Bootstrap's .entry-content styling */ +.entry-summary { + margin-top: 1em; +} + +/* Custom page footer */ +#footer { + padding-top: 19px; + color: #777; + border-top: 1px solid #e5e5e5; +} + +/* hat tip bootstrap/html5 boilerplate */ +@media print { + *, *:before, *:after { + font-family: Garamond, Junicode, serif; + } + + body { + font-size: 12pt; + } + + article .entry-title a[href]:after, + article .metadata a[href]:after, + article .tags a[href]:after { + content: ""; + } + + article .metadata .sourceline { + display: none; + } + + article .metadata .linkline a[href]:after { + content: " (" attr(href) ")"; + } + + .navbar { + display: none; + } +} diff --git a/nikola/data/themes/bootstrap3/assets/fonts/glyphicons-halflings-regular.woff2 b/nikola/data/themes/bootstrap3/assets/fonts/glyphicons-halflings-regular.woff2 new file mode 120000 index 0000000..8c1e4d3 --- /dev/null +++ b/nikola/data/themes/bootstrap3/assets/fonts/glyphicons-halflings-regular.woff2 @@ -0,0 +1 @@ +../../../../../../bower_components/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2
\ No newline at end of file diff --git a/nikola/data/themes/bootstrap3/bundles b/nikola/data/themes/bootstrap3/bundles index 0a96b4f..8bdc591 100644 --- a/nikola/data/themes/bootstrap3/bundles +++ b/nikola/data/themes/bootstrap3/bundles @@ -1,4 +1,4 @@ assets/css/all-nocdn.css=bootstrap.css,rst.css,code.css,colorbox.css,theme.css,custom.css assets/css/all.css=rst.css,code.css,colorbox.css,theme.css,custom.css -assets/js/all-nocdn.js=jquery.min.js,bootstrap.min.js,jquery.colorbox-min.js -assets/js/all.js=jquery.colorbox-min.js +assets/js/all-nocdn.js=jquery.min.js,bootstrap.min.js,jquery.colorbox-min.js,moment-with-locales.min.js,fancydates.js +assets/js/all.js=jquery.colorbox-min.js,moment-with-locales.min.js,fancydates.js diff --git a/nikola/data/themes/bootstrap3/templates/base.tmpl b/nikola/data/themes/bootstrap3/templates/base.tmpl index c463873..16aebce 100644 --- a/nikola/data/themes/bootstrap3/templates/base.tmpl +++ b/nikola/data/themes/bootstrap3/templates/base.tmpl @@ -13,7 +13,7 @@ ${template_hooks['extra_head']()} <!-- Menubar --> -<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation"> +<nav class="navbar navbar-inverse navbar-static-top" role="navigation"> <div class="container"><!-- This keeps the margins nice --> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse"> @@ -22,7 +22,7 @@ ${template_hooks['extra_head']()} <span class="icon-bar"></span> <span class="icon-bar"></span> </button> - <a class="navbar-brand" href="${abs_link('/')}"> + <a class="navbar-brand" href="${abs_link(_link("root", None, lang))}"> %if logo_url: <img src="${logo_url}" alt="${blog_title}" id="logo"> %endif @@ -58,7 +58,7 @@ ${template_hooks['extra_head']()} <!-- End of Menubar --> -<div class="container" id="content"> +<div class="container" id="content" role="main"> <div class="body-content"> <!--Body content--> <div class="row"> @@ -67,7 +67,7 @@ ${template_hooks['extra_head']()} </div> <!--End of body content--> - <footer> + <footer id="footer"> ${content_footer} ${template_hooks['page_footer']()} </footer> @@ -75,7 +75,13 @@ ${template_hooks['extra_head']()} </div> ${base.late_load_js()} - <script>jQuery("a.image-reference").colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});</script> + <script>$('a.image-reference:not(.islink) img:not(.islink)').parent().colorbox({rel:"gal",maxWidth:"100%",maxHeight:"100%",scalePhotos:true});</script> + <!-- fancy dates --> + <script> + moment.locale("${momentjs_locales[lang]}"); + fancydates(${date_fanciness}, ${js_date_format}); + </script> + <!-- end fancy dates --> <%block name="extra_js"></%block> % if annotations and post and not post.meta('noannotations'): ${notes.code()} diff --git a/nikola/data/themes/bootstrap3/templates/base_helper.tmpl b/nikola/data/themes/bootstrap3/templates/base_helper.tmpl index 096c3c2..8ea843a 100644 --- a/nikola/data/themes/bootstrap3/templates/base_helper.tmpl +++ b/nikola/data/themes/bootstrap3/templates/base_helper.tmpl @@ -1,5 +1,6 @@ ## -*- coding: utf-8 -*- +<%namespace name="notes" file="annotation_helper.tmpl" import="*" /> <%def name="html_headstart()"> <!DOCTYPE html> <html @@ -67,19 +68,21 @@ lang="${lang}"> <%def name="late_load_js()"> %if use_bundles: %if use_cdn: - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> - <script src="//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> + <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> <script src="/assets/js/all.js"></script> %else: <script src="/assets/js/all-nocdn.js"></script> %endif %else: %if use_cdn: - <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> - <script src="//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script> + <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> + <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script> %else: <script src="/assets/js/jquery.min.js"></script> <script src="/assets/js/bootstrap.min.js"></script> + <script src="/assets/js/moment-with-locales.min.js"></script> + <script src="/assets/js/fancydates.js"></script> %endif <script src="/assets/js/jquery.colorbox-min.js"></script> %endif @@ -93,14 +96,14 @@ lang="${lang}"> <%def name="html_stylesheets()"> %if use_bundles: %if use_cdn: - <link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"> + <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"> <link href="/assets/css/all.css" rel="stylesheet" type="text/css"> %else: <link href="/assets/css/all-nocdn.css" rel="stylesheet" type="text/css"> %endif %else: %if use_cdn: - <link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"> + <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"> %else: <link href="/assets/css/bootstrap.min.css" rel="stylesheet" type="text/css"> %endif @@ -112,6 +115,10 @@ lang="${lang}"> <link href="/assets/css/custom.css" rel="stylesheet" type="text/css"> %endif %endif + % if needs_ipython_css: + <link href="/assets/css/ipython.min.css" rel="stylesheet" type="text/css"> + <link href="/assets/css/nikola_ipython.css" rel="stylesheet" type="text/css"> + % endif % if annotations and post and not post.meta('noannotations'): ${notes.css()} % elif not annotations and post and post.meta('annotations'): @@ -122,11 +129,11 @@ lang="${lang}"> <%def name="html_navigation_links()"> %for url, text in navigation_links[lang]: % if isinstance(url, tuple): - <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">${text}<b class="caret"></b></a> + <li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown">${text} <b class="caret"></b></a> <ul class="dropdown-menu"> %for suburl, text in url: % if rel_link(permalink, suburl) == "#": - <li class="active"><a href="${permalink}">${text}</a> + <li class="active"><a href="${permalink}">${text} <span class="sr-only">${messages("(active)", lang)}</span></a> %else: <li><a href="${suburl}">${text}</a> %endif @@ -134,7 +141,7 @@ lang="${lang}"> </ul> % else: % if rel_link(permalink, url) == "#": - <li class="active"><a href="${permalink}">${text}</a> + <li class="active"><a href="${permalink}">${text} <span class="sr-only">${messages("(active)", lang)}</span></a> %else: <li><a href="${url}">${text}</a> %endif @@ -154,12 +161,21 @@ lang="${lang}"> <link rel="alternate" type="application/rss+xml" title="RSS" href="${_link('rss', None)}"> %endif %endif + %if generate_atom: + %if len(translations) > 1: + %for language in translations: + <link rel="alternate" type="application/atom+xml" title="Atom (${language})" href="${_link('index_atom', None, language)}"> + %endfor + %else: + <link rel="alternate" type="application/atom+xml" title="Atom" href="${_link('index_atom', None)}"> + %endif + %endif </%def> <%def name="html_translations()"> %for langname in translations.keys(): %if langname != lang: - <li><a href="${_link("index", None, langname)}" rel="alternate" hreflang="${langname}">${messages("LANGUAGE", langname)}</a></li> + <li><a href="${abs_link(_link("root", None, langname))}" rel="alternate" hreflang="${langname}">${messages("LANGUAGE", langname)}</a></li> %endif %endfor </%def> diff --git a/nikola/data/themes/bootstrap3/templates/gallery.tmpl b/nikola/data/themes/bootstrap3/templates/gallery.tmpl index 26fe80d..3d6c01a 100644 --- a/nikola/data/themes/bootstrap3/templates/gallery.tmpl +++ b/nikola/data/themes/bootstrap3/templates/gallery.tmpl @@ -7,7 +7,7 @@ <%block name="content"> ${ui.bar(crumbs)} %if title: - <h1>${title}</h1> + <h1>${title|h}</h1> %endif %if post: <p> @@ -17,8 +17,7 @@ %if folders: <ul> % for folder, ftitle in folders: - <li><a href="${folder}"><i class="glyphicon - glyphicon-folder-open"></i> ${ftitle}</a></li> + <li><a href="${folder}"><i class="glyphicon glyphicon-folder-open"></i> ${ftitle}</a></li> % endfor </ul> %endif @@ -41,6 +40,7 @@ ${comments.comment_form(None, permalink, title)} <%block name="extra_head"> ${parent.extra_head()} +<link rel="alternate" type="application/rss+xml" title="RSS" href="rss.xml"> <style type="text/css"> .image-block { display: inline-block; diff --git a/nikola/filters.py b/nikola/filters.py index 0037004..269aae9 100644 --- a/nikola/filters.py +++ b/nikola/filters.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -147,11 +147,67 @@ def jpegoptim(infile): return runinplace(r"jpegoptim -p --strip-all -q %1", infile) +def html_tidy_withconfig(infile): + return _html_tidy_runner(infile, r"-quiet --show-info no --show-warnings no -utf8 -indent -config tidy5.conf -modify %1") + + +def html_tidy_nowrap(infile): + return _html_tidy_runner(infile, r"-quiet --show-info no --show-warnings no -utf8 -indent --indent-attributes no --sort-attributes alpha --wrap 0 --wrap-sections no --drop-empty-elements no --tidy-mark no -modify %1") + + +def html_tidy_wrap(infile): + return _html_tidy_runner(infile, r"-quiet --show-info no --show-warnings no -utf8 -indent --indent-attributes no --sort-attributes alpha --wrap 80 --wrap-sections no --drop-empty-elements no --tidy-mark no -modify %1") + + +def html_tidy_wrap_attr(infile): + return _html_tidy_runner(infile, r"-quiet --show-info no --show-warnings no -utf8 -indent --indent-attributes yes --sort-attributes alpha --wrap 80 --wrap-sections no --drop-empty-elements no --tidy-mark no -modify %1") + + +def html_tidy_mini(infile): + return _html_tidy_runner(infile, r"-quiet --show-info no --show-warnings no -utf8 --indent-attributes no --sort-attributes alpha --wrap 0 --wrap-sections no --tidy-mark no --drop-empty-elements no -modify %1") + + +def _html_tidy_runner(infile, options): + """ Warnings (returncode 1) are not critical, and *everything* is a warning """ + try: + status = runinplace(r"tidy5 " + options, infile) + except subprocess.CalledProcessError as err: + status = 0 if err.returncode == 1 else err.returncode + return status + + +@apply_to_text_file +def html5lib_minify(data): + import html5lib + import html5lib.serializer + data = html5lib.serializer.serialize(html5lib.parse(data, treebuilder='lxml'), + tree='lxml', + quote_attr_values=False, + omit_optional_tags=True, + minimize_boolean_attributes=True, + strip_whitespace=True, + alphabetical_attributes=True, + escape_lt_in_attrs=True) + return data + + +@apply_to_text_file +def html5lib_xmllike(data): + import html5lib + import html5lib.serializer + data = html5lib.serializer.serialize(html5lib.parse(data, treebuilder='lxml'), + tree='lxml', + quote_attr_values=True, + omit_optional_tags=False, + strip_whitespace=False, + alphabetical_attributes=True, + escape_lt_in_attrs=True) + return data + + @apply_to_text_file def minify_lines(data): - datalines = data.splitlines() - datalines = [line.lstrip() for line in datalines if not (line.strip() == "")] - return "\n".join(datalines) + return data @apply_to_text_file @@ -169,6 +225,21 @@ def typogrify(data): @apply_to_text_file +def typogrify_sans_widont(data): + # typogrify with widont disabled because it caused broken headline + # wrapping, see issue #1465 + if typo is None: + req_missing(['typogrify'], 'use the typogrify_sans_widont filter') + + data = typo.amp(data) + data = typo.smartypants(data) + # Disabled because of typogrify bug where it breaks <title> + # data = typo.caps(data) + data = typo.initial_quotes(data) + return data + + +@apply_to_text_file def php_template_injection(data): import re template = re.search('<\!-- __NIKOLA_PHP_TEMPLATE_INJECTION source\:(.*) checksum\:(.*)__ -->', data) @@ -179,5 +250,6 @@ def php_template_injection(data): _META_SEPARATOR = '(' + os.linesep * 2 + '|' + ('\n' * 2) + '|' + ("\r\n" * 2) + ')' phpdata = re.split(_META_SEPARATOR, phpdata, maxsplit=1)[-1] phpdata = re.sub(template.group(0), phpdata, data) - - return phpdata + return phpdata + else: + return data diff --git a/nikola/image_processing.py b/nikola/image_processing.py new file mode 100644 index 0000000..1e11a50 --- /dev/null +++ b/nikola/image_processing.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- + +# Copyright © 2014 Roberto Alsina and others. + +# 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. + +from __future__ import unicode_literals +import datetime +import os + +from nikola import utils + +Image = None +try: + from PIL import Image, ExifTags # NOQA +except ImportError: + try: + import Image as _Image + import ExifTags + Image = _Image + except ImportError: + pass + + +class ImageProcessor(object): + """Apply image operations.""" + + image_ext_list_builtin = ['.jpg', '.png', '.jpeg', '.gif', '.svg', '.bmp', '.tiff'] + + def resize_image(self, src, dst, max_size, bigger_panoramas=True): + """Make a copy of the image in the requested size.""" + if not Image: + utils.copy_file(src, dst) + return + im = Image.open(src) + w, h = im.size + if w > max_size or h > max_size: + size = max_size, max_size + + # Panoramas get larger thumbnails because they look *awful* + if bigger_panoramas and w > 2 * h: + size = min(w, max_size * 4), min(w, max_size * 4) + + try: + exif = im._getexif() + except Exception: + exif = None + if exif is not None: + for tag, value in list(exif.items()): + decoded = ExifTags.TAGS.get(tag, tag) + + if decoded == 'Orientation': + if value == 3: + im = im.rotate(180) + elif value == 6: + im = im.rotate(270) + elif value == 8: + im = im.rotate(90) + break + try: + im.thumbnail(size, Image.ANTIALIAS) + im.save(dst) + except Exception as e: + self.logger.warn("Can't thumbnail {0}, using original " + "image as thumbnail ({1})".format(src, e)) + utils.copy_file(src, dst) + else: # Image is small + utils.copy_file(src, dst) + + def image_date(self, src): + """Try to figure out the date of the image.""" + if src not in self.dates: + try: + im = Image.open(src) + exif = im._getexif() + except Exception: + exif = None + if exif is not None: + for tag, value in list(exif.items()): + decoded = ExifTags.TAGS.get(tag, tag) + if decoded in ('DateTimeOriginal', 'DateTimeDigitized'): + try: + self.dates[src] = datetime.datetime.strptime( + value, r'%Y:%m:%d %H:%M:%S') + break + except ValueError: # Invalid EXIF date. + pass + if src not in self.dates: + self.dates[src] = datetime.datetime.fromtimestamp( + os.stat(src).st_mtime) + return self.dates[src] diff --git a/nikola/nikola.py b/nikola/nikola.py index 6a3fc0d..2a15568 100644 --- a/nikola/nikola.py +++ b/nikola/nikola.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -30,45 +30,32 @@ from collections import defaultdict from copy import copy from pkg_resources import resource_filename import datetime -import glob import locale import os +import json import sys +import natsort import mimetypes try: - from urlparse import urlparse, urlsplit, urljoin + from urlparse import urlparse, urlsplit, urlunsplit, urljoin, unquote except ImportError: - from urllib.parse import urlparse, urlsplit, urljoin # NOQA + from urllib.parse import urlparse, urlsplit, urlunsplit, urljoin, unquote # NOQA -from blinker import signal try: import pyphen except ImportError: pyphen = None -import dateutil.tz +import dateutil.tz import logging -from . import DEBUG - -if DEBUG: - logging.basicConfig(level=logging.DEBUG) -else: - logging.basicConfig(level=logging.ERROR) - import PyRSS2Gen as rss - +import lxml.etree import lxml.html from yapsy.PluginManager import PluginManager +from blinker import signal -# Default "Read more..." link -DEFAULT_INDEX_READ_MORE_LINK = '<p class="more"><a href="{link}">{read_more}…</a></p>' -DEFAULT_RSS_READ_MORE_LINK = '<p><a href="{link}">{read_more}…</a> ({min_remaining_read})</p>' - -# Default pattern for translation files' names -DEFAULT_TRANSLATIONS_PATTERN = '{path}.{lang}.{ext}' - -from .post import Post -from . import utils +from .post import Post # NOQA +from . import DEBUG, utils from .plugin_categories import ( Command, LateTask, @@ -79,8 +66,22 @@ from .plugin_categories import ( TaskMultiplier, TemplateSystem, SignalHandler, + ConfigPlugin, + PostScanner, ) +if DEBUG: + logging.basicConfig(level=logging.DEBUG) +else: + logging.basicConfig(level=logging.ERROR) + +# Default "Read more..." link +DEFAULT_INDEX_READ_MORE_LINK = '<p class="more"><a href="{link}">{read_more}…</a></p>' +DEFAULT_RSS_READ_MORE_LINK = '<p><a href="{link}">{read_more}…</a> ({min_remaining_read})</p>' + +# Default pattern for translation files' names +DEFAULT_TRANSLATIONS_PATTERN = '{path}.{lang}.{ext}' + config_changed = utils.config_changed @@ -98,9 +99,12 @@ LEGAL_VALUES = { 'muut', ], 'TRANSLATIONS': { + 'ar': 'Arabic', + 'az': 'Azerbaijani', 'bg': 'Bulgarian', 'ca': 'Catalan', ('cs', 'cz'): 'Czech', + 'da': 'Danish', 'de': 'German', ('el', '!gr'): 'Greek', 'en': 'English', @@ -113,8 +117,10 @@ LEGAL_VALUES = { 'fr': 'French', 'hi': 'Hindi', 'hr': 'Croatian', + 'id': 'Indonesian', 'it': 'Italian', ('ja', '!jp'): 'Japanese', + 'ko': 'Korean', 'nb': 'Norwegian Bokmål', 'nl': 'Dutch', 'pl': 'Polish', @@ -122,8 +128,11 @@ LEGAL_VALUES = { 'ru': 'Russian', 'sk': 'Slovak', 'sl': 'Slovene', + 'sr': 'Serbian (Cyrillic)', + 'sv': 'Swedish', ('tr', '!tr_TR'): 'Turkish', 'ur': 'Urdu', + 'uk': 'Ukrainian', 'zh_cn': 'Chinese (Simplified)', }, '_TRANSLATIONS_WITH_COUNTRY_SPECIFIERS': { @@ -132,15 +141,17 @@ LEGAL_VALUES = { # language with a different country, ``nikola init`` (but nobody else!) # will accept it, warning the user about it. 'pt': 'pt_br', - 'zh': 'zh_cn' + 'zh': 'zh_cn', }, 'RTL_LANGUAGES': ('ar', 'fa', 'ur'), 'COLORBOX_LOCALES': defaultdict( str, + ar='ar', bg='bg', ca='ca', cs='cs', cz='cs', + da='da', de='de', en='', es='es', @@ -149,18 +160,80 @@ LEGAL_VALUES = { fi='fi', fr='fr', hr='hr', + id='id', it='it', ja='ja', + ko='kr', # kr is South Korea, ko is the Korean language nb='no', nl='nl', - pt_br='pt-br', pl='pl', + pt_br='pt-BR', ru='ru', sk='sk', sl='si', # country code is si, language code is sl, colorbox is wrong + sr='sr', # warning: this is serbian in Latin alphabet + sv='sv', tr='tr', + uk='uk', zh_cn='zh-CN' - ) + ), + 'MOMENTJS_LOCALES': defaultdict( + str, + ar='ar', + bg='bg', + bn='bn', + ca='ca', + cs='cs', + cz='cs', + da='da', + de='de', + en='', + es='es', + et='et', + fa='fa', + fi='fi', + fr='fr', + hr='hr', + id='id', + it='it', + ja='ja', + ko='ko', + nb='nb', + nl='nl', + pl='pl', + pt_br='pt-br', + ru='ru', + sk='sk', + sl='sl', + sr='sr-cyrl', + sv='sv', + tr='tr', + zh_cn='zh-cn' + ), + 'PYPHEN_LOCALES': { + 'bg': 'bg', + 'ca': 'ca', + 'cs': 'cs', + 'cz': 'cs', + 'da': 'da', + 'de': 'de', + 'el': 'el', + 'en': 'en', + 'es': 'es', + 'et': 'et', + 'fr': 'fr', + 'hr': 'hr', + 'it': 'it', + 'nb': 'nb', + 'nl': 'nl', + 'pl': 'pl', + 'pt_br': 'pt_BR', + 'ru': 'ru', + 'sk': 'sk', + 'sl': 'sl', + 'sr': 'sr', + 'sv': 'sv', + }, } @@ -188,12 +261,13 @@ class Nikola(object): self.path_handlers = { 'slug': self.slug_path, 'post_path': self.post_path, + 'root': self.root_path, 'filename': self.filename_path, } self.strict = False - self.global_data = {} self.posts = [] + self.all_posts = [] self.posts_per_year = defaultdict(list) self.posts_per_month = defaultdict(list) self.posts_per_tag = defaultdict(list) @@ -209,8 +283,13 @@ class Nikola(object): self.colorful = config.pop('__colorful__', False) self.invariant = config.pop('__invariant__', False) self.quiet = config.pop('__quiet__', False) + self._doit_config = config.pop('DOIT_CONFIG', {}) + self.original_cwd = config.pop('__cwd__', False) + self.configuration_filename = config.pop('__configuration_filename__', False) self.configured = bool(config) + self.injected_deps = defaultdict(list) + self.rst_transforms = [] self.template_hooks = { 'extra_head': utils.TemplateHookRegistry('extra_head', self), 'body_end': utils.TemplateHookRegistry('body_end', self), @@ -228,11 +307,18 @@ class Nikola(object): 'ANNOTATIONS': False, 'ARCHIVE_PATH': "", 'ARCHIVE_FILENAME': "archive.html", + 'ARCHIVES_ARE_INDEXES': False, 'BLOG_AUTHOR': 'Default Author', 'BLOG_TITLE': 'Default Title', 'BLOG_DESCRIPTION': 'Default Description', 'BODY_END': "", 'CACHE_FOLDER': 'cache', + 'CATEGORY_PATH': None, # None means: same as TAG_PATH + 'CATEGORY_PAGES_ARE_INDEXES': None, # None means: same as TAG_PAGES_ARE_INDEXES + 'CATEGORY_PAGES_DESCRIPTIONS': {}, + 'CATEGORY_PREFIX': 'cat_', + 'CATEGORY_ALLOW_HIERARCHIES': False, + 'CATEGORY_OUTPUT_FLAT_HIERARCHY': False, 'CODE_COLOR_SCHEME': 'default', 'COMMENT_SYSTEM': 'disqus', 'COMMENTS_IN_GALLERIES': False, @@ -252,54 +338,68 @@ class Nikola(object): 'COPY_SOURCES': True, 'CREATE_MONTHLY_ARCHIVE': False, 'CREATE_SINGLE_ARCHIVE': False, + 'CREATE_FULL_ARCHIVES': False, + 'CREATE_DAILY_ARCHIVE': False, 'DATE_FORMAT': '%Y-%m-%d %H:%M', + 'JS_DATE_FORMAT': 'YYYY-MM-DD HH:mm', + 'DATE_FANCINESS': 0, 'DEFAULT_LANG': "en", - 'DEPLOY_COMMANDS': [], + 'DEPLOY_COMMANDS': {'default': []}, 'DISABLED_PLUGINS': [], 'EXTRA_PLUGINS_DIRS': [], 'COMMENT_SYSTEM_ID': 'nikolademo', 'EXTRA_HEAD_DATA': '', - 'FAVICONS': {}, + 'FAVICONS': (), 'FEED_LENGTH': 10, 'FILE_METADATA_REGEXP': None, 'ADDITIONAL_METADATA': {}, 'FILES_FOLDERS': {'files': ''}, 'FILTERS': {}, 'FORCE_ISO8601': False, - 'GALLERY_PATH': 'galleries', + 'GALLERY_FOLDERS': {'galleries': 'galleries'}, 'GALLERY_SORT_BY_DATE': True, + 'GLOBAL_CONTEXT_FILLER': [], 'GZIP_COMMAND': None, 'GZIP_FILES': False, 'GZIP_EXTENSIONS': ('.txt', '.htm', '.html', '.css', '.js', '.json', '.xml'), + 'HIDDEN_TAGS': [], + 'HIDDEN_CATEGORIES': [], 'HYPHENATE': False, + 'IMAGE_FOLDERS': {'images': ''}, 'INDEX_DISPLAY_POST_COUNT': 10, 'INDEX_FILE': 'index.html', 'INDEX_TEASERS': False, + 'IMAGE_THUMBNAIL_SIZE': 400, 'INDEXES_TITLE': "", 'INDEXES_PAGES': "", 'INDEXES_PAGES_MAIN': False, + 'INDEXES_PRETTY_PAGE_URL': False, + 'INDEXES_STATIC': True, 'INDEX_PATH': '', 'IPYNB_CONFIG': {}, 'LESS_COMPILER': 'lessc', 'LESS_OPTIONS': [], 'LICENSE': '', 'LINK_CHECK_WHITELIST': [], - 'LISTINGS_FOLDER': 'listings', + 'LISTINGS_FOLDERS': {'listings': 'listings'}, 'LOGO_URL': '', 'NAVIGATION_LINKS': {}, - 'MARKDOWN_EXTENSIONS': ['fenced_code', 'codehilite'], + 'MARKDOWN_EXTENSIONS': ['fenced_code', 'codehilite'], # FIXME: Add 'extras' in v8 'MAX_IMAGE_SIZE': 1280, 'MATHJAX_CONFIG': '', 'OLD_THEME_SUPPORT': True, 'OUTPUT_FOLDER': 'output', 'POSTS': (("posts/*.txt", "posts", "post.tmpl"),), 'PAGES': (("stories/*.txt", "stories", "story.tmpl"),), + 'PANDOC_OPTIONS': [], 'PRETTY_URLS': False, 'FUTURE_IS_NOW': False, 'INDEX_READ_MORE_LINK': DEFAULT_INDEX_READ_MORE_LINK, 'RSS_READ_MORE_LINK': DEFAULT_RSS_READ_MORE_LINK, + 'RSS_LINKS_APPEND_QUERY': False, 'REDIRECTIONS': [], 'ROBOTS_EXCLUSIONS': [], + 'GENERATE_ATOM': False, 'GENERATE_RSS': True, 'RSS_LINK': None, 'RSS_PATH': '', @@ -312,13 +412,15 @@ class Nikola(object): 'SHOW_SOURCELINK': True, 'SHOW_UNTRANSLATED_POSTS': True, 'SLUG_TAG_PATH': True, - 'SOCIAL_BUTTONS_CODE': SOCIAL_BUTTONS_CODE, - 'SITE_URL': 'http://getnikola.com/', + 'SOCIAL_BUTTONS_CODE': '', + 'SITE_URL': 'https://example.com/', 'STORY_INDEX': False, 'STRIP_INDEXES': False, 'SITEMAP_INCLUDE_FILELESS_DIRS': True, 'TAG_PATH': 'categories', 'TAG_PAGES_ARE_INDEXES': False, + 'TAG_PAGES_DESCRIPTIONS': {}, + 'TAGLIST_MINIMUM_POSTS': 1, 'TEMPLATE_FILTERS': {}, 'THEME': 'bootstrap', 'THEME_REVEAL_CONFIG_SUBTHEME': 'sky', @@ -328,16 +430,21 @@ class Nikola(object): 'URL_TYPE': 'rel_path', 'USE_BUNDLES': True, 'USE_CDN': False, + 'USE_CDN_WARNING': True, 'USE_FILENAME_AS_TITLE': True, 'USE_OPEN_GRAPH': True, 'USE_SLUGIFY': True, 'TIMEZONE': 'UTC', + 'WRITE_TAG_CLOUD': True, 'DEPLOY_DRAFTS': True, 'DEPLOY_FUTURE': False, 'SCHEDULE_ALL': False, 'SCHEDULE_RULE': '', 'LOGGING_HANDLERS': {'stderr': {'loglevel': 'WARNING', 'bubble': True}}, 'DEMOTE_HEADERS': 1, + 'GITHUB_SOURCE_BRANCH': 'master', + 'GITHUB_DEPLOY_BRANCH': 'gh-pages', + 'GITHUB_REMOTE_NAME': 'origin', } # set global_context for template rendering @@ -376,7 +483,10 @@ class Nikola(object): 'EXTRA_HEAD_DATA', 'NAVIGATION_LINKS', 'INDEX_READ_MORE_LINK', - 'RSS_READ_MORE_LINK',) + 'RSS_READ_MORE_LINK', + 'INDEXES_TITLE', + 'INDEXES_PAGES', + 'INDEXES_PRETTY_PAGE_URL',) self._GLOBAL_CONTEXT_TRANSLATABLE = ('blog_author', 'blog_title', @@ -478,28 +588,77 @@ class Nikola(object): if self.config.get('PRETTY_URLS') and 'STRIP_INDEXES' not in config: self.config['STRIP_INDEXES'] = True + if 'LISTINGS_FOLDER' in config: + if 'LISTINGS_FOLDERS' not in config: + utils.LOGGER.warn("The LISTINGS_FOLDER option is deprecated, use LISTINGS_FOLDERS instead.") + self.config['LISTINGS_FOLDERS'] = {self.config['LISTINGS_FOLDER']: self.config['LISTINGS_FOLDER']} + utils.LOGGER.warn("LISTINGS_FOLDERS = {0}".format(self.config['LISTINGS_FOLDERS'])) + else: + utils.LOGGER.warn("Both LISTINGS_FOLDER and LISTINGS_FOLDERS are specified, ignoring LISTINGS_FOLDER.") + + if 'GALLERY_PATH' in config: + if 'GALLERY_FOLDERS' not in config: + utils.LOGGER.warn("The GALLERY_PATH option is deprecated, use GALLERY_FOLDERS instead.") + self.config['GALLERY_FOLDERS'] = {self.config['GALLERY_PATH']: self.config['GALLERY_PATH']} + utils.LOGGER.warn("GALLERY_FOLDERS = {0}".format(self.config['GALLERY_FOLDERS'])) + else: + utils.LOGGER.warn("Both GALLERY_PATH and GALLERY_FOLDERS are specified, ignoring GALLERY_PATH.") + if not self.config.get('COPY_SOURCES'): self.config['SHOW_SOURCELINK'] = False + if self.config['CATEGORY_PATH'] is None: + self.config['CATEGORY_PATH'] = self.config['TAG_PATH'] + if self.config['CATEGORY_PAGES_ARE_INDEXES'] is None: + self.config['CATEGORY_PAGES_ARE_INDEXES'] = self.config['TAG_PAGES_ARE_INDEXES'] + self.default_lang = self.config['DEFAULT_LANG'] self.translations = self.config['TRANSLATIONS'] - if self.configured: - locale_fallback, locale_default, locales = sanitized_locales( - self.config.get('LOCALE_FALLBACK', None), - self.config.get('LOCALE_DEFAULT', None), - self.config.get('LOCALES', {}), self.translations) - utils.LocaleBorg.initialize(locales, self.default_lang) + locale_fallback, locale_default, locales = sanitized_locales( + self.config.get('LOCALE_FALLBACK', None), + self.config.get('LOCALE_DEFAULT', None), + self.config.get('LOCALES', {}), self.translations) + utils.LocaleBorg.initialize(locales, self.default_lang) # BASE_URL defaults to SITE_URL if 'BASE_URL' not in self.config: self.config['BASE_URL'] = self.config.get('SITE_URL') # BASE_URL should *always* end in / if self.config['BASE_URL'] and self.config['BASE_URL'][-1] != '/': - utils.LOGGER.warn("Your BASE_URL doesn't end in / -- adding it.") + utils.LOGGER.warn("Your BASE_URL doesn't end in / -- adding it, but please fix it in your config file!") + self.config['BASE_URL'] += '/' + + try: + _bnl = urlsplit(self.config['BASE_URL']).netloc + _bnl.encode('ascii') + urlsplit(self.config['SITE_URL']).netloc.encode('ascii') + except (UnicodeEncodeError, UnicodeDecodeError): + utils.LOGGER.error("Your BASE_URL or SITE_URL contains an IDN expressed in Unicode. Please convert it to Punycode.") + utils.LOGGER.error("Punycode of {}: {}".format(_bnl, _bnl.encode('idna'))) + sys.exit(1) + + # TODO: remove in v8 + if not isinstance(self.config['DEPLOY_COMMANDS'], dict): + utils.LOGGER.warn("A single list as DEPLOY_COMMANDS is deprecated. DEPLOY_COMMANDS should be a dict, with deploy preset names as keys and lists of commands as values.") + utils.LOGGER.warn("The key `default` is used by `nikola deploy`:") + self.config['DEPLOY_COMMANDS'] = {'default': self.config['DEPLOY_COMMANDS']} + utils.LOGGER.warn("DEPLOY_COMMANDS = {0}".format(self.config['DEPLOY_COMMANDS'])) + utils.LOGGER.info("(The above can be used with `nikola deploy` or `nikola deploy default`. Multiple presets are accepted.)") + + # TODO: remove and change default in v8 + if 'BLOG_TITLE' in config and 'WRITE_TAG_CLOUD' not in config: + # BLOG_TITLE is a hack, otherwise the warning would be displayed + # when conf.py does not exist + utils.LOGGER.warn("WRITE_TAG_CLOUD is not set in your config. Defaulting to True (== writing tag_cloud_data.json).") + utils.LOGGER.warn("Please explicitly add the setting to your conf.py with the desired value, as the setting will default to False in the future.") # We use one global tzinfo object all over Nikola. - self.tzinfo = dateutil.tz.gettz(self.config['TIMEZONE']) + try: + self.tzinfo = dateutil.tz.gettz(self.config['TIMEZONE']) + except Exception as exc: + utils.LOGGER.warn("Error getting TZ: {}", exc) + self.tzinfo = dateutil.tz.gettz() self.config['__tzinfo__'] = self.tzinfo self.plugin_manager = PluginManager(categories_filter={ @@ -512,6 +671,8 @@ class Nikola(object): "RestExtension": RestExtension, "MarkdownExtension": MarkdownExtension, "SignalHandler": SignalHandler, + "ConfigPlugin": ConfigPlugin, + "PostScanner": PostScanner, }) self.plugin_manager.setPluginInfoExtension('plugin') extra_plugins_dirs = self.config['EXTRA_PLUGINS_DIRS'] @@ -531,45 +692,27 @@ class Nikola(object): self.plugin_manager.setPluginPlaces(places) self.plugin_manager.collectPlugins() - # Activate all required SignalHandler plugins - for plugin_info in self.plugin_manager.getPluginsOfCategory("SignalHandler"): - if plugin_info.name in self.config.get('DISABLED_PLUGINS'): - self.plugin_manager.removePluginFromCategory(plugin_info, "SignalHandler") - else: - self.plugin_manager.activatePluginByName(plugin_info.name) - plugin_info.plugin_object.set_site(self) + self._activate_plugins_of_category("SignalHandler") # Emit signal for SignalHandlers which need to start running immediately. signal('sighandlers_loaded').send(self) self._commands = {} - # Activate all command plugins - for plugin_info in self.plugin_manager.getPluginsOfCategory("Command"): - if plugin_info.name in self.config['DISABLED_PLUGINS']: - self.plugin_manager.removePluginFromCategory(plugin_info, "Command") - continue - - self.plugin_manager.activatePluginByName(plugin_info.name) - plugin_info.plugin_object.set_site(self) + + command_plugins = self._activate_plugins_of_category("Command") + for plugin_info in command_plugins: plugin_info.plugin_object.short_help = plugin_info.description self._commands[plugin_info.name] = plugin_info.plugin_object - # Activate all task plugins - for task_type in ["Task", "LateTask"]: - for plugin_info in self.plugin_manager.getPluginsOfCategory(task_type): - if plugin_info.name in self.config['DISABLED_PLUGINS']: - self.plugin_manager.removePluginFromCategory(plugin_info, task_type) - continue - self.plugin_manager.activatePluginByName(plugin_info.name) - plugin_info.plugin_object.set_site(self) + self._activate_plugins_of_category("PostScanner") + self._activate_plugins_of_category("Task") + self._activate_plugins_of_category("LateTask") + self._activate_plugins_of_category("TaskMultiplier") - # Activate all multiplier plugins - for plugin_info in self.plugin_manager.getPluginsOfCategory("TaskMultiplier"): - if plugin_info.name in self.config['DISABLED_PLUGINS']: - self.plugin_manager.removePluginFromCategory(plugin_info, task_type) - continue - self.plugin_manager.activatePluginByName(plugin_info.name) - plugin_info.plugin_object.set_site(self) + # Store raw compilers for internal use (need a copy for that) + self.config['_COMPILERS_RAW'] = {} + for k, v in self.config['COMPILERS'].items(): + self.config['_COMPILERS_RAW'][k] = list(v) compilers = defaultdict(set) # Also add aliases for combinations with TRANSLATIONS_PATTERN @@ -604,11 +747,11 @@ class Nikola(object): self._GLOBAL_CONTEXT['annotations'] = self.config['ANNOTATIONS'] self._GLOBAL_CONTEXT['index_display_post_count'] = self.config[ 'INDEX_DISPLAY_POST_COUNT'] + self._GLOBAL_CONTEXT['index_file'] = self.config['INDEX_FILE'] self._GLOBAL_CONTEXT['use_bundles'] = self.config['USE_BUNDLES'] self._GLOBAL_CONTEXT['use_cdn'] = self.config.get("USE_CDN") self._GLOBAL_CONTEXT['favicons'] = self.config['FAVICONS'] - self._GLOBAL_CONTEXT['date_format'] = self.config.get( - 'DATE_FORMAT', '%Y-%m-%d %H:%M') + self._GLOBAL_CONTEXT['date_format'] = self.config.get('DATE_FORMAT') self._GLOBAL_CONTEXT['blog_author'] = self.config.get('BLOG_AUTHOR') self._GLOBAL_CONTEXT['blog_title'] = self.config.get('BLOG_TITLE') self._GLOBAL_CONTEXT['show_blog_title'] = self.config.get('SHOW_BLOG_TITLE') @@ -634,6 +777,7 @@ class Nikola(object): self._GLOBAL_CONTEXT['transition'] = self.config.get('THEME_REVEAL_CONFIG_TRANSITION') self._GLOBAL_CONTEXT['content_footer'] = self.config.get( 'CONTENT_FOOTER') + self._GLOBAL_CONTEXT['generate_atom'] = self.config.get('GENERATE_ATOM') self._GLOBAL_CONTEXT['generate_rss'] = self.config.get('GENERATE_RSS') self._GLOBAL_CONTEXT['rss_path'] = self.config.get('RSS_PATH') self._GLOBAL_CONTEXT['rss_link'] = self.config.get('RSS_LINK') @@ -649,9 +793,24 @@ class Nikola(object): self._GLOBAL_CONTEXT['show_sourcelink'] = self.config.get( 'SHOW_SOURCELINK') self._GLOBAL_CONTEXT['extra_head_data'] = self.config.get('EXTRA_HEAD_DATA') + self._GLOBAL_CONTEXT['date_fanciness'] = self.config.get('DATE_FANCINESS') + self._GLOBAL_CONTEXT['js_date_format'] = json.dumps(self.config.get('JS_DATE_FORMAT')) self._GLOBAL_CONTEXT['colorbox_locales'] = LEGAL_VALUES['COLORBOX_LOCALES'] + self._GLOBAL_CONTEXT['momentjs_locales'] = LEGAL_VALUES['MOMENTJS_LOCALES'] + self._GLOBAL_CONTEXT['hidden_tags'] = self.config.get('HIDDEN_TAGS') + self._GLOBAL_CONTEXT['hidden_categories'] = self.config.get('HIDDEN_CATEGORIES') self._GLOBAL_CONTEXT['url_replacer'] = self.url_replacer + # IPython theme configuration. If a website can potentially have ipynb + # posts (as determined by checking POSTS/PAGES against ipynb + # extensions), we should enable the IPython CSS (leaving that up to the + # theme itself). + + self._GLOBAL_CONTEXT['needs_ipython_css'] = False + for i in self.config['post_pages']: + if os.path.splitext(i[0])[1] in self.config['COMPILERS'].get('ipynb', []): + self._GLOBAL_CONTEXT['needs_ipython_css'] = True + self._GLOBAL_CONTEXT.update(self.config.get('GLOBAL_CONTEXT', {})) # Load compiler plugins @@ -663,8 +822,22 @@ class Nikola(object): self.compilers[plugin_info.name] = \ plugin_info.plugin_object + self._activate_plugins_of_category("ConfigPlugin") + signal('configured').send(self) + def _activate_plugins_of_category(self, category): + """Activate all the plugins of a given category and return them.""" + plugins = [] + for plugin_info in self.plugin_manager.getPluginsOfCategory(category): + if plugin_info.name in self.config.get('DISABLED_PLUGINS'): + self.plugin_manager.removePluginFromCategory(plugin_info, category) + else: + self.plugin_manager.activatePluginByName(plugin_info.name) + plugin_info.plugin_object.set_site(self) + plugins.append(plugin_info) + return plugins + def _get_themes(self): if self._THEMES is None: try: @@ -674,7 +847,7 @@ class Nikola(object): self.config['THEME'] = 'bootstrap' return self._get_themes() # Check consistency of USE_CDN and the current THEME (Issue #386) - if self.config['USE_CDN']: + if self.config['USE_CDN'] and self.config['USE_CDN_WARNING']: bootstrap_path = utils.get_asset_path(os.path.join( 'assets', 'css', 'bootstrap.min.css'), self._THEMES) if bootstrap_path and bootstrap_path.split(os.sep)[-4] not in ['bootstrap', 'bootstrap3']: @@ -763,12 +936,23 @@ class Nikola(object): "handle '{0}' extensions.".format(ext)) lang = langs[0] - compile_html = self.compilers[lang] + try: + compile_html = self.compilers[lang] + except KeyError: + exit("Cannot find '{0}' compiler; it might require an extra plugin -- do you have it installed?".format(lang)) self.inverse_compilers[ext] = compile_html return compile_html def render_template(self, template_name, output_name, context): + """Render a template with the global context. + + If ``output_name`` is None, will return a string and all URL + normalization will be ignored (including the link:// scheme). + If ``output_name`` is a string, URLs will be normalized and + the resultant HTML will be saved to the named file (path must + start with OUTPUT_FOLDER). + """ local_context = {} local_context["template_name"] = template_name local_context.update(self.GLOBAL_CONTEXT) @@ -781,9 +965,15 @@ class Nikola(object): for h in local_context['template_hooks'].values(): h.context = context + for func in self.config['GLOBAL_CONTEXT_FILLER']: + func(local_context, template_name) + data = self.template_system.render_template( template_name, None, local_context) + if output_name is None: + return data + assert output_name.startswith( self.config["OUTPUT_FOLDER"]) url_part = output_name[len(self.config["OUTPUT_FOLDER"]) + 1:] @@ -796,13 +986,14 @@ class Nikola(object): src = "/".join(src.split(os.sep)) utils.makedirs(os.path.dirname(output_name)) - doc = lxml.html.document_fromstring(data) + parser = lxml.html.HTMLParser(remove_blank_text=True) + doc = lxml.html.document_fromstring(data, parser) doc.rewrite_links(lambda dst: self.url_replacer(src, dst, context['lang'])) data = b'<!DOCTYPE html>\n' + lxml.html.tostring(doc, encoding='utf8', method='html', pretty_print=True) with open(output_name, "wb+") as post_file: post_file.write(data) - def url_replacer(self, src, dst, lang=None): + def url_replacer(self, src, dst, lang=None, url_type=None): """URL mangler. * Replaces link:// URLs with real links @@ -814,19 +1005,42 @@ class Nikola(object): src is the URL where this link is used dst is the link to be mangled lang is used for language-sensitive URLs in link:// - + url_type is used to determine final link appearance, defaulting to URL_TYPE from config """ parsed_src = urlsplit(src) src_elems = parsed_src.path.split('/')[1:] dst_url = urlparse(dst) if lang is None: lang = self.default_lang + if url_type is None: + url_type = self.config.get('URL_TYPE') + + if dst_url.scheme and dst_url.scheme not in ['http', 'https', 'link']: + return dst # Refuse to replace links that are full URLs. if dst_url.netloc: if dst_url.scheme == 'link': # Magic link dst = self.link(dst_url.netloc, dst_url.path.lstrip('/'), lang) + # Assuming the site is served over one of these, and + # since those are the only URLs we want to rewrite... else: + if '%' in dst_url.netloc: + # convert lxml percent-encoded garbage to punycode + nl = unquote(dst_url.netloc) + try: + nl = nl.decode('utf-8') + except AttributeError: + # python 3: already unicode + pass + nl = nl.encode('idna') + if isinstance(nl, utils.bytes_str): + nl = nl.decode('latin-1') # so idna stays unchanged + dst = urlunsplit((dst_url.scheme, + nl, + dst_url.path, + dst_url.query, + dst_url.fragment)) return dst elif dst_url.scheme == 'link': # Magic absolute path link: dst = dst_url.path @@ -843,10 +1057,10 @@ class Nikola(object): # Avoid empty links. if src == dst: - if self.config.get('URL_TYPE') == 'absolute': + if url_type == 'absolute': dst = urljoin(self.config['BASE_URL'], dst.lstrip('/')) return dst - elif self.config.get('URL_TYPE') == 'full_path': + elif url_type == 'full_path': dst = urljoin(self.config['BASE_URL'], dst.lstrip('/')) return urlparse(dst).path else: @@ -855,13 +1069,13 @@ class Nikola(object): # Check that link can be made relative, otherwise return dest parsed_dst = urlsplit(dst) if parsed_src[:2] != parsed_dst[:2]: - if self.config.get('URL_TYPE') == 'absolute': + if url_type == 'absolute': dst = urljoin(self.config['BASE_URL'], dst) return dst - if self.config.get('URL_TYPE') in ('full_path', 'absolute'): + if url_type in ('full_path', 'absolute'): dst = urljoin(self.config['BASE_URL'], dst.lstrip('/')) - if self.config.get('URL_TYPE') == 'full_path': + if url_type == 'full_path': parsed = urlparse(urljoin(self.config['BASE_URL'], dst.lstrip('/'))) if parsed.fragment: dst = '{0}#{1}'.format(parsed.path, parsed.fragment) @@ -895,31 +1109,41 @@ class Nikola(object): return result def generic_rss_renderer(self, lang, title, link, description, timeline, output_path, - rss_teasers, rss_plain, feed_length=10, feed_url=None, enclosure=_enclosure): + rss_teasers, rss_plain, feed_length=10, feed_url=None, + enclosure=_enclosure, rss_links_append_query=None): """Takes all necessary data, and renders a RSS feed in output_path.""" - rss_obj = rss.RSS2( + rss_obj = utils.ExtendedRSS2( title=title, link=link, description=description, - lastBuildDate=datetime.datetime.now(), + lastBuildDate=datetime.datetime.utcnow(), generator='http://getnikola.com/', language=lang ) + if feed_url: + absurl = '/' + feed_url[len(self.config['BASE_URL']):] + rss_obj.xsl_stylesheet_href = self.url_replacer(absurl, "/assets/xml/rss.xsl") + items = [] + feed_append_query = None + if rss_links_append_query: + feed_append_query = rss_links_append_query.format( + feedRelUri='/' + feed_url[len(self.config['BASE_URL']):], + feedFormat="rss") + for post in timeline[:feed_length]: - old_url_type = self.config['URL_TYPE'] - self.config['URL_TYPE'] = 'absolute' - data = post.text(lang, teaser_only=rss_teasers, strip_html=rss_plain, rss_read_more_link=True) + data = post.text(lang, teaser_only=rss_teasers, strip_html=rss_plain, + rss_read_more_link=True, rss_links_append_query=feed_append_query) if feed_url is not None and data: # Massage the post's HTML (unless plain) if not rss_plain: # FIXME: this is duplicated with code in Post.text() try: doc = lxml.html.document_fromstring(data) - doc.rewrite_links(lambda dst: self.url_replacer(post.permalink(), dst, lang)) + doc.rewrite_links(lambda dst: self.url_replacer(post.permalink(), dst, lang, 'absolute')) try: body = doc.body data = (body.text or '') + ''.join( @@ -932,32 +1156,33 @@ class Nikola(object): data = "" else: # let other errors raise raise(e) - self.config['URL_TYPE'] = old_url_type args = { 'title': post.title(lang), - 'link': post.permalink(lang, absolute=True), + 'link': post.permalink(lang, absolute=True, query=feed_append_query), 'description': data, - 'guid': post.permalink(lang, absolute=True), # PyRSS2Gen's pubDate is GMT time. 'pubDate': (post.date if post.date.tzinfo is None else post.date.astimezone(dateutil.tz.tzutc())), 'categories': post._tags.get(lang, []), 'creator': post.author(lang), + 'guid': post.permalink(lang, absolute=True), } if post.author(lang): rss_obj.rss_attrs["xmlns:dc"] = "http://purl.org/dc/elements/1.1/" - """ Enclosure callback must returns tuple """ - # enclosure callback returns None if post has no enclosure, or a - # 3-tuple of (url, length (0 is valid), mimetype) - enclosure_details = enclosure(post=post, lang=lang) - if enclosure_details is not None: - args['enclosure'] = rss.Enclosure(*enclosure_details) + if enclosure: + # enclosure callback returns None if post has no enclosure, or a + # 3-tuple of (url, length (0 is valid), mimetype) + enclosure_details = enclosure(post=post, lang=lang) + if enclosure_details is not None: + args['enclosure'] = rss.Enclosure(*enclosure_details) items.append(utils.ExtendedItem(**args)) rss_obj.items = items + rss_obj.self_url = feed_url + rss_obj.rss_attrs["xmlns:atom"] = "http://www.w3.org/2005/Atom" dst_dir = os.path.dirname(output_path) utils.makedirs(dst_dir) @@ -970,12 +1195,13 @@ class Nikola(object): def path(self, kind, name, lang=None, is_link=False): """Build the path to a certain kind of page. - These are mostly defined by plugins by registering via - the register_path_handler method, except for slug and - post_path which are defined in this class' init method. + These are mostly defined by plugins by registering via the + register_path_handler method, except for slug, post_path, root + and filename which are defined in this class' init method. Here's some of the others, for historical reasons: + * root (name is ignored) * tag_index (name is ignored) * tag (and name is the tag name) * tag_rss (name is the tag name) @@ -1027,6 +1253,14 @@ class Nikola(object): os.path.dirname(name), self.config['INDEX_FILE']] if _f] + def root_path(self, name, lang): + """root_path path handler""" + d = self.config['TRANSLATIONS'][lang] + if d: + return [d, ''] + else: + return [] + def slug_path(self, name, lang): """slug path handler""" results = [p for p in self.timeline if p.meta('slug') == name] @@ -1121,6 +1355,9 @@ class Nikola(object): for task in flatten(pluginInfo.plugin_object.gen_tasks()): assert 'basename' in task task = self.clean_task_paths(task) + if 'task_dep' not in task: + task['task_dep'] = [] + task['task_dep'].extend(self.injected_deps[task['basename']]) yield task for multi in self.plugin_manager.getPluginsOfCategory("TaskMultiplier"): flag = False @@ -1139,108 +1376,132 @@ class Nikola(object): 'task_dep': task_dep } - def scan_posts(self, really=False): - """Scan all the posts.""" + def parse_category_name(self, category_name): + if self.config['CATEGORY_ALLOW_HIERARCHIES']: + try: + return utils.parse_escaped_hierarchical_category_name(category_name) + except Exception as e: + utils.LOGGER.error(str(e)) + sys.exit(1) + else: + return [category_name] if len(category_name) > 0 else [] + + def category_path_to_category_name(self, category_path): + if self.config['CATEGORY_ALLOW_HIERARCHIES']: + return utils.join_hierarchical_category_path(category_path) + else: + return ''.join(category_path) + + def _add_post_to_category(self, post, category_name): + category_path = self.parse_category_name(category_name) + current_path = [] + current_subtree = self.category_hierarchy + for current in category_path: + current_path.append(current) + if current not in current_subtree: + current_subtree[current] = {} + current_subtree = current_subtree[current] + self.posts_per_category[self.category_path_to_category_name(current_path)].append(post) + + def _sort_category_hierarchy(self): + # First create a hierarchy of TreeNodes + self.category_hierarchy_lookup = {} + + def create_hierarchy(cat_hierarchy, parent=None): + result = [] + for name, children in cat_hierarchy.items(): + node = utils.TreeNode(name, parent) + node.children = create_hierarchy(children, node) + node.category_path = [pn.name for pn in node.get_path()] + node.category_name = self.category_path_to_category_name(node.category_path) + self.category_hierarchy_lookup[node.category_name] = node + if node.category_name not in self.config.get('HIDDEN_CATEGORIES'): + result.append(node) + return natsort.natsorted(result, key=lambda e: e.name, alg=natsort.ns.F | natsort.ns.IC) + + root_list = create_hierarchy(self.category_hierarchy) + # Next, flatten the hierarchy + self.category_hierarchy = utils.flatten_tree_structure(root_list) + + def scan_posts(self, really=False, ignore_quit=False, quiet=False): + """Scan all the posts. + + Ignoring quiet. + """ if self._scanned and not really: return - self.commands = utils.Commands(self.doit) - self.global_data = {} + # Reset things self.posts = [] + self.all_posts = [] self.posts_per_year = defaultdict(list) self.posts_per_month = defaultdict(list) self.posts_per_tag = defaultdict(list) self.posts_per_category = defaultdict(list) + self.category_hierarchy = {} self.post_per_file = {} self.timeline = [] self.pages = [] - seen = set([]) - if not self.quiet: - print("Scanning posts", end='', file=sys.stderr) - slugged_tags = set([]) + for p in self.plugin_manager.getPluginsOfCategory('PostScanner'): + timeline = p.plugin_object.scan() + # FIXME: can there be conflicts here? + self.timeline.extend(timeline) + quit = False - for wildcard, destination, template_name, use_in_feeds in \ - self.config['post_pages']: - if not self.quiet: - print(".", end='', file=sys.stderr) - dirname = os.path.dirname(wildcard) - for dirpath, _, _ in os.walk(dirname, followlinks=True): - dest_dir = os.path.normpath(os.path.join(destination, - os.path.relpath(dirpath, dirname))) # output/destination/foo/ - # Get all the untranslated paths - dir_glob = os.path.join(dirpath, os.path.basename(wildcard)) # posts/foo/*.rst - untranslated = glob.glob(dir_glob) - # And now get all the translated paths - translated = set([]) - for lang in self.config['TRANSLATIONS'].keys(): - if lang == self.config['DEFAULT_LANG']: - continue - lang_glob = utils.get_translation_candidate(self.config, dir_glob, lang) # posts/foo/*.LANG.rst - translated = translated.union(set(glob.glob(lang_glob))) - # untranslated globs like *.rst often match translated paths too, so remove them - # and ensure x.rst is not in the translated set - untranslated = set(untranslated) - translated - - # also remove from translated paths that are translations of - # paths in untranslated_list, so x.es.rst is not in the untranslated set - for p in untranslated: - translated = translated - set([utils.get_translation_candidate(self.config, p, l) for l in self.config['TRANSLATIONS'].keys()]) - - full_list = list(translated) + list(untranslated) - # We eliminate from the list the files inside any .ipynb folder - full_list = [p for p in full_list - if not any([x.startswith('.') - for x in p.split(os.sep)])] - - for base_path in full_list: - if base_path in seen: - continue - else: - seen.add(base_path) - post = Post( - base_path, - self.config, - dest_dir, - use_in_feeds, - self.MESSAGES, - template_name, - self.get_compiler(base_path) - ) - self.timeline.append(post) - self.global_data[post.source_path] = post - if post.use_in_feeds: - self.posts.append(post) - self.posts_per_year[ - str(post.date.year)].append(post) - self.posts_per_month[ - '{0}/{1:02d}'.format(post.date.year, post.date.month)].append(post) - for tag in post.alltags: - _tag_slugified = utils.slugify(tag) - if _tag_slugified in slugged_tags: - if tag not in self.posts_per_tag: - # Tags that differ only in case - other_tag = [existing for existing in self.posts_per_tag.keys() if utils.slugify(existing) == _tag_slugified][0] - utils.LOGGER.error('You have tags that are too similar: {0} and {1}'.format(tag, other_tag)) - utils.LOGGER.error('Tag {0} is used in: {1}'.format(tag, post.source_path)) - utils.LOGGER.error('Tag {0} is used in: {1}'.format(other_tag, ', '.join([p.source_path for p in self.posts_per_tag[other_tag]]))) - quit = True - else: - slugged_tags.add(utils.slugify(tag, force=True)) - self.posts_per_tag[tag].append(post) - self.posts_per_category[post.meta('category')].append(post) + # Classify posts per year/tag/month/whatever + slugged_tags = set([]) + for post in self.timeline: + if post.use_in_feeds: + self.posts.append(post) + self.posts_per_year[str(post.date.year)].append(post) + self.posts_per_month[ + '{0}/{1:02d}'.format(post.date.year, post.date.month)].append(post) + for tag in post.alltags: + _tag_slugified = utils.slugify(tag) + if _tag_slugified in slugged_tags: + if tag not in self.posts_per_tag: + # Tags that differ only in case + other_tag = [existing for existing in self.posts_per_tag.keys() if utils.slugify(existing) == _tag_slugified][0] + utils.LOGGER.error('You have tags that are too similar: {0} and {1}'.format(tag, other_tag)) + utils.LOGGER.error('Tag {0} is used in: {1}'.format(tag, post.source_path)) + utils.LOGGER.error('Tag {0} is used in: {1}'.format(other_tag, ', '.join([p.source_path for p in self.posts_per_tag[other_tag]]))) + quit = True else: - self.pages.append(post) - self.post_per_file[post.destination_path(lang=lang)] = post - self.post_per_file[post.destination_path(lang=lang, extension=post.source_ext())] = post + slugged_tags.add(utils.slugify(tag, force=True)) + self.posts_per_tag[tag].append(post) + self._add_post_to_category(post, post.meta('category')) + + if post.is_post: + # unpublished posts + self.all_posts.append(post) + else: + self.pages.append(post) + + for lang in self.config['TRANSLATIONS'].keys(): + dest = post.destination_path(lang=lang) + src_dest = post.destination_path(lang=lang, extension=post.source_ext()) + if dest in self.post_per_file: + utils.LOGGER.error('Two posts are trying to generate {0}: {1} and {2}'.format( + dest, + self.post_per_file[dest].source_path, + post.source_path)) + quit = True + if (src_dest in self.post_per_file) and self.config['COPY_SOURCES']: + utils.LOGGER.error('Two posts are trying to generate {0}: {1} and {2}'.format( + src_dest, + self.post_per_file[dest].source_path, + post.source_path)) + quit = True + self.post_per_file[dest] = post + self.post_per_file[src_dest] = post # Sort everything. - self.timeline.sort(key=lambda p: p.date) - self.timeline.reverse() - self.posts.sort(key=lambda p: p.date) - self.posts.reverse() - self.pages.sort(key=lambda p: p.date) - self.pages.reverse() + + for thing in self.timeline, self.posts, self.all_posts, self.pages: + thing.sort(key=lambda p: (p.date, p.source_path)) + thing.reverse() + self._sort_category_hierarchy() for i, p in enumerate(self.posts[1:]): p.next_post = self.posts[i] @@ -1249,11 +1510,9 @@ class Nikola(object): self._scanned = True if not self.quiet: print("done!", file=sys.stderr) - - signal('scanned').send(self) - - if quit: + if quit and not ignore_quit: sys.exit(1) + signal('scanned').send(self) def generic_page_renderer(self, lang, post, filters): """Render post fragments to final HTML pages.""" @@ -1303,7 +1562,7 @@ class Nikola(object): 'actions': [(self.render_template, [post.template_name, output_name, context])], 'clean': True, - 'uptodate': [config_changed(deps_dict)], + 'uptodate': [config_changed(deps_dict, 'nikola.nikola.Nikola.generic_page_renderer')] + post.deps_uptodate(lang), } yield utils.apply_filters(task, filters) @@ -1313,8 +1572,10 @@ class Nikola(object): """Renders pages with lists of posts.""" deps = self.template_system.template_deps(template_name) + uptodate_deps = [] for post in posts: deps += post.deps(lang) + uptodate_deps += post.deps_uptodate(lang) context = {} context["posts"] = posts context["title"] = self.config['BLOG_TITLE'](lang) @@ -1343,11 +1604,314 @@ class Nikola(object): 'actions': [(self.render_template, [template_name, output_name, context])], 'clean': True, - 'uptodate': [config_changed(deps_context)] + 'uptodate': [config_changed(deps_context, 'nikola.nikola.Nikola.generic_post_list_renderer')] + uptodate_deps } return utils.apply_filters(task, filters) + def atom_feed_renderer(self, lang, posts, output_path, filters, + extra_context): + """Renders Atom feeds and archives with lists of posts. Feeds are + considered archives when no future updates to them are expected""" + + def atom_link(link_rel, link_type, link_href): + link = lxml.etree.Element("link") + link.set("rel", link_rel) + link.set("type", link_type) + link.set("href", link_href) + return link + + deps = [] + uptodate_deps = [] + for post in posts: + deps += post.deps(lang) + uptodate_deps += post.deps_uptodate(lang) + context = {} + context["posts"] = posts + context["title"] = self.config['BLOG_TITLE'](lang) + context["description"] = self.config['BLOG_DESCRIPTION'](lang) + context["lang"] = lang + context["prevlink"] = None + context["nextlink"] = None + context["is_feed_stale"] = None + context.update(extra_context) + deps_context = copy(context) + deps_context["posts"] = [(p.meta[lang]['title'], p.permalink(lang)) for p in + posts] + deps_context["global"] = self.GLOBAL_CONTEXT + + for k in self._GLOBAL_CONTEXT_TRANSLATABLE: + deps_context[k] = deps_context['global'][k](lang) + + deps_context['navigation_links'] = deps_context['global']['navigation_links'](lang) + + nslist = {} + if context["is_feed_stale"] or (not context["feedpagenum"] == context["feedpagecount"] - 1 and not context["feedpagenum"] == 0): + nslist["fh"] = "http://purl.org/syndication/history/1.0" + if not self.config["RSS_TEASERS"]: + nslist["xh"] = "http://www.w3.org/1999/xhtml" + feed_xsl_link = self.abs_link("/assets/xml/atom.xsl") + feed_root = lxml.etree.Element("feed", nsmap=nslist) + feed_root.addprevious(lxml.etree.ProcessingInstruction( + "xml-stylesheet", + 'href="' + feed_xsl_link + '" type="text/xsl media="all"')) + feed_root.set("{http://www.w3.org/XML/1998/namespace}lang", lang) + feed_root.set("xmlns", "http://www.w3.org/2005/Atom") + feed_title = lxml.etree.SubElement(feed_root, "title") + feed_title.text = context["title"] + feed_id = lxml.etree.SubElement(feed_root, "id") + feed_id.text = self.abs_link(context["feedlink"]) + feed_updated = lxml.etree.SubElement(feed_root, "updated") + feed_updated.text = datetime.datetime.now(tz=dateutil.tz.tzutc()).replace(microsecond=0).isoformat() + feed_author = lxml.etree.SubElement(feed_root, "author") + feed_author_name = lxml.etree.SubElement(feed_author, "name") + feed_author_name.text = self.config["BLOG_AUTHOR"](lang) + feed_root.append(atom_link("self", "application/atom+xml", + self.abs_link(context["feedlink"]))) + # Older is "next" and newer is "previous" in paginated feeds (opposite of archived) + if "nextfeedlink" in context: + feed_root.append(atom_link("next", "application/atom+xml", + self.abs_link(context["nextfeedlink"]))) + if "prevfeedlink" in context: + feed_root.append(atom_link("previous", "application/atom+xml", + self.abs_link(context["prevfeedlink"]))) + if context["is_feed_stale"] or not context["feedpagenum"] == 0: + feed_root.append(atom_link("current", "application/atom+xml", + self.abs_link(context["currentfeedlink"]))) + # Older is "prev-archive" and newer is "next-archive" in archived feeds (opposite of paginated) + if "prevfeedlink" in context and (context["is_feed_stale"] or not context["feedpagenum"] == context["feedpagecount"] - 1): + feed_root.append(atom_link("next-archive", "application/atom+xml", + self.abs_link(context["prevfeedlink"]))) + if "nextfeedlink" in context: + feed_root.append(atom_link("prev-archive", "application/atom+xml", + self.abs_link(context["nextfeedlink"]))) + if context["is_feed_stale"] or not context["feedpagenum"] == context["feedpagecount"] - 1: + lxml.etree.SubElement(feed_root, "{http://purl.org/syndication/history/1.0}archive") + feed_root.append(atom_link("alternate", "text/html", + self.abs_link(context["permalink"]))) + feed_generator = lxml.etree.SubElement(feed_root, "generator") + feed_generator.set("uri", "http://getnikola.com/") + feed_generator.text = "Nikola" + + feed_append_query = None + if self.config["RSS_LINKS_APPEND_QUERY"]: + feed_append_query = self.config["RSS_LINKS_APPEND_QUERY"].format( + feedRelUri=context["feedlink"], + feedFormat="atom") + + for post in posts: + data = post.text(lang, teaser_only=self.config["RSS_TEASERS"], strip_html=self.config["RSS_TEASERS"], + rss_read_more_link=True, rss_links_append_query=feed_append_query) + if not self.config["RSS_TEASERS"]: + # FIXME: this is duplicated with code in Post.text() and generic_rss_renderer + try: + doc = lxml.html.document_fromstring(data) + doc.rewrite_links(lambda dst: self.url_replacer(post.permalink(), dst, lang, 'absolute')) + try: + body = doc.body + data = (body.text or '') + ''.join( + [lxml.html.tostring(child, encoding='unicode') + for child in body.iterchildren()]) + except IndexError: # No body there, it happens sometimes + data = '' + except lxml.etree.ParserError as e: + if str(e) == "Document is empty": + data = "" + else: # let other errors raise + raise(e) + + entry_root = lxml.etree.SubElement(feed_root, "entry") + entry_title = lxml.etree.SubElement(entry_root, "title") + entry_title.text = post.title(lang) + entry_id = lxml.etree.SubElement(entry_root, "id") + entry_id.text = post.permalink(lang, absolute=True) + entry_updated = lxml.etree.SubElement(entry_root, "updated") + entry_updated.text = post.updated.isoformat() + entry_published = lxml.etree.SubElement(entry_root, "published") + entry_published.text = post.date.isoformat() + entry_author = lxml.etree.SubElement(entry_root, "author") + entry_author_name = lxml.etree.SubElement(entry_author, "name") + entry_author_name.text = post.author(lang) + entry_root.append(atom_link("alternate", "text/html", + post.permalink(lang, absolute=True, + query=feed_append_query))) + if self.config["RSS_TEASERS"]: + entry_summary = lxml.etree.SubElement(entry_root, "summary") + entry_summary.text = data + else: + entry_content = lxml.etree.SubElement(entry_root, "content") + entry_content.set("type", "xhtml") + entry_content_nsdiv = lxml.etree.SubElement(entry_content, "{http://www.w3.org/1999/xhtml}div") + entry_content_nsdiv.text = data + for category in post.tags: + entry_category = lxml.etree.SubElement(entry_root, "category") + entry_category.set("term", utils.slugify(category)) + entry_category.set("label", category) + + dst_dir = os.path.dirname(output_path) + utils.makedirs(dst_dir) + with io.open(output_path, "w+", encoding="utf-8") as atom_file: + data = lxml.etree.tostring(feed_root.getroottree(), encoding="UTF-8", pretty_print=True, xml_declaration=True) + if isinstance(data, utils.bytes_str): + data = data.decode('utf-8') + atom_file.write(data) + + def generic_index_renderer(self, lang, posts, indexes_title, template_name, context_source, kw, basename, page_link, page_path, additional_dependencies=[]): + """Creates an index page. + + lang: The language + posts: A list of posts + indexes_title: Title + template_name: Name of template file + context_source: This will be copied and extended and used as every + page's context + kw: An extended version will be used for uptodate dependencies + basename: Basename for task + page_link: A function accepting an index i, the displayed page number, + the number of pages, and a boolean force_addition + which creates a link to the i-th page (where i ranges + between 0 and num_pages-1). The displayed page (between 1 + and num_pages) is the number (optionally) displayed as + 'page %d' on the rendered page. If force_addition is True, + the appendum (inserting '-%d' etc.) should be done also for + i == 0. + page_path: A function accepting an index i, the displayed page number, + the number of pages, and a boolean force_addition, + which creates a path to the i-th page. All arguments are + as the ones for page_link. + additional_dependencies: a list of dependencies which will be added + to task['uptodate'] + """ + # Update kw + kw = kw.copy() + kw["tag_pages_are_indexes"] = self.config['TAG_PAGES_ARE_INDEXES'] + kw["index_display_post_count"] = self.config['INDEX_DISPLAY_POST_COUNT'] + kw["index_teasers"] = self.config['INDEX_TEASERS'] + kw["indexes_pages"] = self.config['INDEXES_PAGES'](lang) + kw["indexes_pages_main"] = self.config['INDEXES_PAGES_MAIN'] + kw["indexes_static"] = self.config['INDEXES_STATIC'] + kw['indexes_prety_page_url'] = self.config["INDEXES_PRETTY_PAGE_URL"] + kw['demote_headers'] = self.config['DEMOTE_HEADERS'] + kw['generate_atom'] = self.config["GENERATE_ATOM"] + kw['feed_link_append_query'] = self.config["RSS_LINKS_APPEND_QUERY"] + kw['feed_teasers'] = self.config["RSS_TEASERS"] + kw['currentfeed'] = None + + # Split in smaller lists + lists = [] + if kw["indexes_static"]: + lists.append(posts[:kw["index_display_post_count"]]) + posts = posts[kw["index_display_post_count"]:] + while posts: + lists.append(posts[-kw["index_display_post_count"]:]) + posts = posts[:-kw["index_display_post_count"]] + else: + while posts: + lists.append(posts[:kw["index_display_post_count"]]) + posts = posts[kw["index_display_post_count"]:] + num_pages = len(lists) + for i, post_list in enumerate(lists): + context = context_source.copy() + ipages_i = utils.get_displayed_page_number(i, num_pages, self) + if kw["indexes_pages"]: + indexes_pages = kw["indexes_pages"] % ipages_i + else: + if kw["indexes_pages_main"]: + ipages_msg = "page %d" + else: + ipages_msg = "old posts, page %d" + indexes_pages = " (" + \ + kw["messages"][lang][ipages_msg] % ipages_i + ")" + if i > 0 or kw["indexes_pages_main"]: + context["title"] = indexes_title + indexes_pages + else: + context["title"] = indexes_title + context["prevlink"] = None + context["nextlink"] = None + context['index_teasers'] = kw['index_teasers'] + prevlink = None + nextlink = None + if kw["indexes_static"]: + if i > 0: + if i < num_pages - 1: + prevlink = i + 1 + elif i == num_pages - 1: + prevlink = 0 + if num_pages > 1: + if i > 1: + nextlink = i - 1 + elif i == 0: + nextlink = num_pages - 1 + else: + if i >= 1: + prevlink = i - 1 + if i < num_pages - 1: + nextlink = i + 1 + if prevlink is not None: + context["prevlink"] = page_link(prevlink, + utils.get_displayed_page_number(prevlink, num_pages, self), + num_pages, False) + context["prevfeedlink"] = page_link(prevlink, + utils.get_displayed_page_number(prevlink, num_pages, self), + num_pages, False, extension=".atom") + if nextlink is not None: + context["nextlink"] = page_link(nextlink, + utils.get_displayed_page_number(nextlink, num_pages, self), + num_pages, False) + context["nextfeedlink"] = page_link(nextlink, + utils.get_displayed_page_number(nextlink, num_pages, self), + num_pages, False, extension=".atom") + context["permalink"] = page_link(i, ipages_i, num_pages, False) + output_name = os.path.join(kw['output_folder'], page_path(i, ipages_i, num_pages, False)) + task = self.generic_post_list_renderer( + lang, + post_list, + output_name, + template_name, + kw['filters'], + context, + ) + task['uptodate'] = task['uptodate'] + [utils.config_changed(kw, 'nikola.nikola.Nikola.generic_index_renderer')] + additional_dependencies + task['basename'] = basename + yield task + + if kw['generate_atom']: + atom_output_name = os.path.join(kw['output_folder'], page_path(i, ipages_i, num_pages, False, extension=".atom")) + context["feedlink"] = page_link(i, ipages_i, num_pages, False, extension=".atom") + if not kw["currentfeed"]: + kw["currentfeed"] = context["feedlink"] + context["currentfeedlink"] = kw["currentfeed"] + context["feedpagenum"] = i + context["feedpagecount"] = num_pages + atom_task = { + "basename": basename, + "file_dep": [output_name], + "name": atom_output_name, + "targets": [atom_output_name], + "actions": [(self.atom_feed_renderer, + (lang, + post_list, + atom_output_name, + kw['filters'], + context,))], + "clean": True, + "uptodate": [utils.config_changed(kw, 'nikola.nikola.Nikola.atom_feed_renderer')] + additional_dependencies + } + yield utils.apply_filters(atom_task, kw['filters']) + + if kw["indexes_pages_main"] and kw['indexes_prety_page_url'](lang): + # create redirection + output_name = os.path.join(kw['output_folder'], page_path(0, utils.get_displayed_page_number(0, num_pages, self), num_pages, True)) + link = page_link(0, utils.get_displayed_page_number(0, num_pages, self), num_pages, False) + yield utils.apply_filters({ + 'basename': basename, + 'name': output_name, + 'targets': [output_name], + 'actions': [(utils.create_redirect, (output_name, link))], + 'clean': True, + 'uptodate': [utils.config_changed(kw, 'nikola.nikola.Nikola.generic_index_renderer')], + }, kw["filters"]) + def __repr__(self): return '<Nikola Site: {0!r}>'.format(self.config['BLOG_TITLE']()) @@ -1526,18 +2090,3 @@ _windows_locale_guesses = { "tr_tr": "Turkish", "zh_cn": "Chinese_China", # Chinese (Simplified) } - - -SOCIAL_BUTTONS_CODE = """ -<!-- Social buttons --> -<div id="addthisbox" class="addthis_toolbox addthis_peekaboo_style addthis_default_style addthis_label_style addthis_32x32_style"> -<a class="addthis_button_more">Share</a> -<ul><li><a class="addthis_button_facebook"></a> -<li><a class="addthis_button_google_plusone_share"></a> -<li><a class="addthis_button_linkedin"></a> -<li><a class="addthis_button_twitter"></a> -</ul> -</div> -<script src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-4f7088a56bb93798"></script> -<!-- End of social buttons --> -""" diff --git a/nikola/packages/__init__.py b/nikola/packages/__init__.py index e69de29..0a704f5 100644 --- a/nikola/packages/__init__.py +++ b/nikola/packages/__init__.py @@ -0,0 +1 @@ +# Packages vendored in by Nikola. diff --git a/nikola/packages/tzlocal/darwin.py b/nikola/packages/tzlocal/darwin.py index 8aeee51..8bfe807 100644 --- a/nikola/packages/tzlocal/darwin.py +++ b/nikola/packages/tzlocal/darwin.py @@ -1,17 +1,26 @@ from __future__ import with_statement import os import dateutil.tz +import subprocess _cache_tz = None def _get_localzone(): - tzname = os.popen("systemsetup -gettimezone").read().replace("Time Zone: ", "").strip() + tzname = subprocess.check_output(["systemsetup", "-gettimezone"]).decode('utf-8') + tzname = tzname.replace("Time Zone: ", "") + # OS X 10.9+, this command is root-only + if 'exiting!' in tzname: + tzname = '' + if not tzname: # link will be something like /usr/share/zoneinfo/America/Los_Angeles. link = os.readlink("/etc/localtime") - tzname = link[link.rfind('/', 0, link.rfind('/')) + 1:] + tzname = link.split('zoneinfo/')[-1] + tzname = tzname.strip() try: + # test the name + assert tzname dateutil.tz.gettz(tzname) return tzname except: diff --git a/nikola/packages/tzlocal/unix.py b/nikola/packages/tzlocal/unix.py index 8e913b8..4cd3752 100644 --- a/nikola/packages/tzlocal/unix.py +++ b/nikola/packages/tzlocal/unix.py @@ -30,7 +30,7 @@ def _get_localzone(): try: # link will be something like /usr/share/zoneinfo/America/Los_Angeles. link = os.readlink('/etc/localtime') - tz = link[link.rfind('/', 0, link.rfind('/')) + 1:] + tz = link.split('zoneinfo/')[-1] if tz: dateutil.tz.gettz(tz) diff --git a/nikola/plugin_categories.py b/nikola/plugin_categories.py index 5eab806..e9af6b5 100644 --- a/nikola/plugin_categories.py +++ b/nikola/plugin_categories.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -27,6 +27,12 @@ from __future__ import absolute_import import sys import os +import re + +from yapsy.IPlugin import IPlugin +from doit.cmd_base import Command as DoitCommand + +from .utils import LOGGER, first_line __all__ = [ 'Command', @@ -37,14 +43,11 @@ __all__ = [ 'Task', 'TaskMultiplier', 'TemplateSystem', - 'SignalHandler' + 'SignalHandler', + 'ConfigPlugin', + 'PostScanner', ] -from yapsy.IPlugin import IPlugin -from doit.cmd_base import Command as DoitCommand - -from .utils import LOGGER, first_line - class BasePlugin(IPlugin): """Base plugin class.""" @@ -75,6 +78,18 @@ class BasePlugin(IPlugin): # so let’s just ignore it and be done with it. pass + def inject_dependency(self, target, dependency): + """Add 'dependency' to the target task's task_deps""" + self.site.injected_deps[target].append(dependency) + + +class PostScanner(BasePlugin): + """The scan method of these plugins is called by Nikola.scan_posts.""" + + def scan(self): + """Creates a list of posts from some source. Returns a list of Post objects.""" + raise NotImplementedError() + class Command(BasePlugin, DoitCommand): """These plugins are exposed via the command line. @@ -93,13 +108,21 @@ class Command(BasePlugin, DoitCommand): BasePlugin.__init__(self, *args, **kwargs) DoitCommand.__init__(self) - def execute(self, options={}, args=[]): + def __call__(self, config=None, **kwargs): + self._doitargs = kwargs + DoitCommand.__init__(self, config, **kwargs) + return self + + def execute(self, options=None, args=None): """Check if the command can run in the current environment, fail if needed, or call _execute.""" + options = options or {} + args = args or [] + if self.needs_config and not self.site.configured: LOGGER.error("This command needs to run inside an existing Nikola site.") return False - self._execute(options, args) + return self._execute(options, args) def _execute(self, options, args): """Do whatever this command does. @@ -117,7 +140,7 @@ def help(self): text.append('') text.append("Options:") - for opt in self.options: + for opt in self.cmdparser.options: text.extend(opt.help_doc()) if self.doc_description is not None: @@ -208,20 +231,28 @@ class TaskMultiplier(BasePlugin): class PageCompiler(BasePlugin): """Plugins that compile text files into HTML.""" - name = "dummy compiler" + name = "dummy_compiler" + friendly_name = '' demote_headers = False supports_onefile = True - default_metadata = {} - default_metadata = { 'title': '', 'slug': '', 'date': '', 'tags': '', + 'category': '', 'link': '', 'description': '', 'type': 'text', } + config_dependencies = [] + + def register_extra_dependencies(self, post): + """Add additional dependencies to the post object. + + Current main use is the ReST page compiler, which puts extra + dependencies into a .deb file.""" + pass def compile_html(self, source, dest, is_two_file=False): """Compile the source, save it on dest.""" @@ -235,6 +266,23 @@ class PageCompiler(BasePlugin): """The preferred extension for the output of this compiler.""" return ".html" + def read_metadata(self, post, file_metadata_regexp=None, unslugify_titles=False, lang=None): + """ + Read the metadata from a post, and return a metadata dict + """ + return {} + + def split_metadata(self, data): + """Split data from metadata in the raw post content. + + This splits in the first empty line that is NOT at the beginning + of the document.""" + split_result = re.split('(\n\n|\r\n\r\n)', data.lstrip(), maxsplit=1) + if len(split_result) == 1: + return '', split_result[0] + # ['metadata', '\n\n', 'post content'] + return split_result[0], split_result[-1] + class RestExtension(BasePlugin): name = "dummy_rest_extension" @@ -248,6 +296,11 @@ class SignalHandler(BasePlugin): name = "dummy_signal_handler" +class ConfigPlugin(BasePlugin): + """A plugin that can edit config (or modify the site) on-the-fly.""" + name = "dummy_config_plugin" + + class Importer(Command): """Basic structure for importing data into Nikola. diff --git a/nikola/plugins/basic_import.py b/nikola/plugins/basic_import.py index 764968a..f8a3a3c 100644 --- a/nikola/plugins/basic_import.py +++ b/nikola/plugins/basic_import.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -29,6 +29,7 @@ import io import csv import datetime import os +import sys from pkg_resources import resource_filename try: @@ -114,32 +115,34 @@ class ImportMixin(object): return content @classmethod - def write_content(cls, filename, content): - doc = html.document_fromstring(content) - doc.rewrite_links(replacer) + def write_content(cls, filename, content, rewrite_html=True): + if rewrite_html: + doc = html.document_fromstring(content) + doc.rewrite_links(replacer) + content = html.tostring(doc, encoding='utf8') + else: + content = content.encode('utf-8') utils.makedirs(os.path.dirname(filename)) with open(filename, "wb+") as fd: - fd.write(html.tostring(doc, encoding='utf8')) + fd.write(content) @staticmethod - def write_metadata(filename, title, slug, post_date, description, tags): + def write_metadata(filename, title, slug, post_date, description, tags, **kwargs): if not description: description = "" utils.makedirs(os.path.dirname(filename)) with io.open(filename, "w+", encoding="utf8") as fd: - fd.write('{0}\n'.format(title)) - fd.write('{0}\n'.format(slug)) - fd.write('{0}\n'.format(post_date)) - fd.write('{0}\n'.format(','.join(tags))) - fd.write('\n') - fd.write('{0}\n'.format(description)) + data = {'title': title, 'slug': slug, 'date': post_date, 'tags': ','.join(tags), 'description': description} + data.update(kwargs) + fd.write(utils.write_metadata(data)) @staticmethod def write_urlmap_csv(output_file, url_map): utils.makedirs(os.path.dirname(output_file)) - with io.open(output_file, 'w+', encoding='utf8') as fd: + fmode = 'wb+' if sys.version_info[0] == 2 else 'w+' + with io.open(output_file, fmode) as fd: csv_writer = csv.writer(fd) for item in url_map.items(): csv_writer.writerow(item) diff --git a/nikola/plugins/command/__init__.py b/nikola/plugins/command/__init__.py index 6ad8bac..a1d17a6 100644 --- a/nikola/plugins/command/__init__.py +++ b/nikola/plugins/command/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/auto.plugin b/nikola/plugins/command/auto.plugin index 87939b2..a1c6820 100644 --- a/nikola/plugins/command/auto.plugin +++ b/nikola/plugins/command/auto.plugin @@ -4,6 +4,6 @@ Module = auto [Documentation] Author = Roberto Alsina -Version = 0.2 +Version = 2.1.0 Website = http://getnikola.com Description = Automatically detect site changes, rebuild and optionally refresh a browser. diff --git a/nikola/plugins/command/auto.py b/nikola/plugins/command/auto.py deleted file mode 100644 index 7f3f66f..0000000 --- a/nikola/plugins/command/auto.py +++ /dev/null @@ -1,87 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright © 2012-2014 Roberto Alsina and others. - -# 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. - -from __future__ import print_function, unicode_literals - -import os -import subprocess - -from nikola.plugin_categories import Command -from nikola.utils import req_missing - - -class CommandAuto(Command): - """Start debugging console.""" - name = "auto" - doc_purpose = "automatically detect site changes, rebuild and optionally refresh a browser" - cmd_options = [ - { - 'name': 'browser', - 'short': 'b', - 'type': bool, - 'help': 'Start a web browser.', - 'default': False, - }, - { - 'name': 'port', - 'short': 'p', - 'long': 'port', - 'default': 8000, - 'type': int, - 'help': 'Port nummber (default: 8000)', - }, - ] - - def _execute(self, options, args): - """Start the watcher.""" - try: - from livereload import Server - except ImportError: - req_missing(['livereload'], 'use the "auto" command') - return - - # Run an initial build so we are up-to-date - subprocess.call(("nikola", "build")) - - port = options and options.get('port') - - server = Server() - server.watch('conf.py', 'nikola build') - server.watch('themes/', 'nikola build') - server.watch('templates/', 'nikola build') - server.watch(self.site.config['GALLERY_PATH'], 'nikola build') - for item in self.site.config['post_pages']: - server.watch(os.path.dirname(item[0]), 'nikola build') - for item in self.site.config['FILES_FOLDERS']: - server.watch(item, 'nikola build') - - out_folder = self.site.config['OUTPUT_FOLDER'] - if options and options.get('browser'): - browser = True - else: - browser = False - - server.serve(port, None, out_folder, True, browser) diff --git a/nikola/plugins/command/auto/__init__.py b/nikola/plugins/command/auto/__init__.py new file mode 100644 index 0000000..c25ef8a --- /dev/null +++ b/nikola/plugins/command/auto/__init__.py @@ -0,0 +1,366 @@ +# -*- coding: utf-8 -*- + +# Copyright © 2012-2015 Roberto Alsina and others. + +# 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. + +from __future__ import print_function + +import json +import mimetypes +import os +import re +import subprocess +try: + from urlparse import urlparse +except ImportError: + from urllib.parse import urlparse # NOQA +import webbrowser +from wsgiref.simple_server import make_server +import wsgiref.util + +from blinker import signal +try: + from ws4py.websocket import WebSocket + from ws4py.server.wsgirefserver import WSGIServer, WebSocketWSGIRequestHandler + from ws4py.server.wsgiutils import WebSocketWSGIApplication + from ws4py.messaging import TextMessage +except ImportError: + WebSocket = object +try: + import watchdog + from watchdog.observers import Observer + from watchdog.events import FileSystemEventHandler, PatternMatchingEventHandler +except ImportError: + watchdog = None + FileSystemEventHandler = object + PatternMatchingEventHandler = object + + +from nikola.plugin_categories import Command +from nikola.utils import req_missing, get_logger, get_theme_path +LRJS_PATH = os.path.join(os.path.dirname(__file__), 'livereload.js') +error_signal = signal('error') +refresh_signal = signal('refresh') + +ERROR_N = '''<html> +<head> +</head> +<boody> +ERROR {} +</body> +</html> +''' + + +class CommandAuto(Command): + """Start debugging console.""" + name = "auto" + logger = None + doc_purpose = "builds and serves a site; automatically detects site changes, rebuilds, and optionally refreshes a browser" + cmd_options = [ + { + 'name': 'port', + 'short': 'p', + 'long': 'port', + 'default': 8000, + 'type': int, + 'help': 'Port nummber (default: 8000)', + }, + { + 'name': 'address', + 'short': 'a', + 'long': 'address', + 'type': str, + 'default': '127.0.0.1', + 'help': 'Address to bind (default: 127.0.0.1 – localhost)', + }, + { + 'name': 'browser', + 'short': 'b', + 'long': 'browser', + 'type': bool, + 'help': 'Start a web browser.', + 'default': False, + }, + { + 'name': 'ipv6', + 'short': '6', + 'long': 'ipv6', + 'default': False, + 'type': bool, + 'help': 'Use IPv6', + }, + ] + + def _execute(self, options, args): + """Start the watcher.""" + + self.logger = get_logger('auto', self.site.loghandlers) + LRSocket.logger = self.logger + + if WebSocket is object and watchdog is None: + req_missing(['ws4py', 'watchdog'], 'use the "auto" command') + elif WebSocket is object: + req_missing(['ws4py'], 'use the "auto" command') + elif watchdog is None: + req_missing(['watchdog'], 'use the "auto" command') + + self.cmd_arguments = ['nikola', 'build'] + if self.site.configuration_filename != 'conf.py': + self.cmd_arguments = ['--conf=' + self.site.configuration_filename] + self.cmd_arguments + + # Run an initial build so we are up-to-date + subprocess.call(self.cmd_arguments) + + port = options and options.get('port') + self.snippet = '''<script>document.write('<script src="http://' + + (location.host || 'localhost').split(':')[0] + + ':{0}/livereload.js?snipver=1"></' + + 'script>')</script> + </head>'''.format(port) + + # Do not duplicate entries -- otherwise, multiple rebuilds are triggered + watched = set([ + 'templates/', + ] + [get_theme_path(name) for name in self.site.THEMES]) + for item in self.site.config['post_pages']: + watched.add(os.path.dirname(item[0])) + for item in self.site.config['FILES_FOLDERS']: + watched.add(item) + for item in self.site.config['GALLERY_FOLDERS']: + watched.add(item) + for item in self.site.config['LISTINGS_FOLDERS']: + watched.add(item) + + out_folder = self.site.config['OUTPUT_FOLDER'] + if options and options.get('browser'): + browser = True + else: + browser = False + + if options['ipv6']: + dhost = '::' + else: + dhost = None + + host = options['address'].strip('[').strip(']') or dhost + + # Instantiate global observer + observer = Observer() + # Watch output folders and trigger reloads + observer.schedule(OurWatchHandler(self.do_refresh), out_folder, recursive=True) + + # Watch input folders and trigger rebuilds + for p in watched: + if os.path.exists(p): + observer.schedule(OurWatchHandler(self.do_rebuild), p, recursive=True) + + # Watch config file (a bit of a hack, but we need a directory) + _conf_fn = os.path.abspath(self.site.configuration_filename or 'conf.py') + _conf_dn = os.path.dirname(_conf_fn) + observer.schedule(ConfigWatchHandler(_conf_fn, self.do_rebuild), _conf_dn, recursive=False) + + observer.start() + + parent = self + + class Mixed(WebSocketWSGIApplication): + """A class that supports WS and HTTP protocols in the same port.""" + def __call__(self, environ, start_response): + if environ.get('HTTP_UPGRADE') is None: + return parent.serve_static(environ, start_response) + return super(Mixed, self).__call__(environ, start_response) + + ws = make_server( + host, port, server_class=WSGIServer, + handler_class=WebSocketWSGIRequestHandler, + app=Mixed(handler_cls=LRSocket) + ) + ws.initialize_websockets_manager() + self.logger.info("Serving HTTP on {0} port {1}...".format(host, port)) + if browser: + if options['ipv6'] or '::' in host: + server_url = "http://[{0}]:{1}/".format(host, port) + else: + server_url = "http://{0}:{1}/".format(host, port) + + self.logger.info("Opening {0} in the default web browser...".format(server_url)) + # Yes, this is racy + webbrowser.open('http://{0}:{1}'.format(host, port)) + + try: + ws.serve_forever() + except KeyboardInterrupt: + self.logger.info("Server is shutting down.") + observer.stop() + observer.join() + + def do_rebuild(self, event): + self.logger.info('REBUILDING SITE (from {0})'.format(event.src_path)) + p = subprocess.Popen(self.cmd_arguments, stderr=subprocess.PIPE) + if p.wait() != 0: + error = p.stderr.read() + self.logger.error(error) + error_signal.send(error=error) + else: + error = p.stderr.read() + print(error) + + def do_refresh(self, event): + self.logger.info('REFRESHING: {0}'.format(event.src_path)) + p = os.path.relpath(event.src_path, os.path.abspath(self.site.config['OUTPUT_FOLDER'])) + refresh_signal.send(path=p) + + def serve_static(self, environ, start_response): + """Trivial static file server.""" + uri = wsgiref.util.request_uri(environ) + p_uri = urlparse(uri) + f_path = os.path.join(self.site.config['OUTPUT_FOLDER'], *p_uri.path.split('/')) + mimetype = mimetypes.guess_type(uri)[0] or 'text/html' + + if os.path.isdir(f_path): + f_path = os.path.join(f_path, self.site.config['INDEX_FILE']) + + if p_uri.path == '/robots.txt': + start_response('200 OK', [('Content-type', 'text/plain')]) + return ['User-Agent: *\nDisallow: /\n'] + elif os.path.isfile(f_path): + with open(f_path, 'rb') as fd: + start_response('200 OK', [('Content-type', mimetype)]) + return [self.inject_js(mimetype, fd.read())] + elif p_uri.path == '/livereload.js': + with open(LRJS_PATH, 'rb') as fd: + start_response('200 OK', [('Content-type', mimetype)]) + return [self.inject_js(mimetype, fd.read())] + start_response('404 ERR', []) + return [self.inject_js('text/html', ERROR_N.format(404).format(uri))] + + def inject_js(self, mimetype, data): + """Inject livereload.js in HTML files.""" + if mimetype == 'text/html': + data = re.sub('</head>', self.snippet, data.decode('utf8'), 1, re.IGNORECASE) + data = data.encode('utf8') + return data + + +pending = [] + + +class LRSocket(WebSocket): + """Speak Livereload protocol.""" + + def __init__(self, *a, **kw): + refresh_signal.connect(self.notify) + error_signal.connect(self.send_error) + super(LRSocket, self).__init__(*a, **kw) + + def received_message(self, message): + message = json.loads(message.data.decode('utf8')) + self.logger.info('<--- {0}'.format(message)) + response = None + if message['command'] == 'hello': # Handshake + response = { + 'command': 'hello', + 'protocols': [ + 'http://livereload.com/protocols/official-7', + ], + 'serverName': 'nikola-livereload', + } + elif message['command'] == 'info': # Someone connected + self.logger.info('****** Browser connected: {0}'.format(message.get('url'))) + self.logger.info('****** sending {0} pending messages'.format(len(pending))) + while pending: + msg = pending.pop() + self.logger.info('---> {0}'.format(msg.data)) + self.send(msg, msg.is_binary) + else: + response = { + 'command': 'alert', + 'message': 'HEY', + } + if response is not None: + response = json.dumps(response) + self.logger.info('---> {0}'.format(response)) + response = TextMessage(response) + self.send(response, response.is_binary) + + def notify(self, sender, path): + """Send reload requests to the client.""" + p = os.path.join('/', path) + message = { + 'command': 'reload', + 'liveCSS': True, + 'path': p, + } + response = json.dumps(message) + self.logger.info('---> {0}'.format(p)) + response = TextMessage(response) + if self.stream is None: # No client connected or whatever + pending.append(response) + else: + self.send(response, response.is_binary) + + def send_error(self, sender, error=None): + """Send reload requests to the client.""" + if self.stream is None: # No client connected or whatever + return + message = { + 'command': 'alert', + 'message': error, + } + response = json.dumps(message) + response = TextMessage(response) + if self.stream is None: # No client connected or whatever + pending.append(response) + else: + self.send(response, response.is_binary) + + +class OurWatchHandler(FileSystemEventHandler): + + """A Nikola-specific handler for Watchdog.""" + + def __init__(self, function): + """Initialize the handler.""" + self.function = function + super(OurWatchHandler, self).__init__() + + def on_any_event(self, event): + """Call the provided function on any event.""" + self.function(event) + + +class ConfigWatchHandler(FileSystemEventHandler): + + """A Nikola-specific handler for Watchdog that handles the config file (as a workaround).""" + + def __init__(self, configuration_filename, function): + """Initialize the handler.""" + self.configuration_filename = configuration_filename + self.function = function + + def on_any_event(self, event): + """Call the provided function on any event.""" + if event._src_path == self.configuration_filename: + self.function(event) diff --git a/nikola/plugins/command/auto/livereload.js b/nikola/plugins/command/auto/livereload.js new file mode 120000 index 0000000..b4cafb3 --- /dev/null +++ b/nikola/plugins/command/auto/livereload.js @@ -0,0 +1 @@ +../../../../bower_components/livereload-js/dist/livereload.js
\ No newline at end of file diff --git a/nikola/plugins/command/bootswatch_theme.plugin b/nikola/plugins/command/bootswatch_theme.plugin index 7091310..b428da3 100644 --- a/nikola/plugins/command/bootswatch_theme.plugin +++ b/nikola/plugins/command/bootswatch_theme.plugin @@ -4,7 +4,7 @@ Module = bootswatch_theme [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Given a swatch name and a parent theme, creates a custom theme. diff --git a/nikola/plugins/command/bootswatch_theme.py b/nikola/plugins/command/bootswatch_theme.py index e65413b..e19c937 100644 --- a/nikola/plugins/command/bootswatch_theme.py +++ b/nikola/plugins/command/bootswatch_theme.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -26,11 +26,7 @@ from __future__ import print_function import os - -try: - import requests -except ImportError: - requests = None # NOQA +import requests from nikola.plugin_categories import Command from nikola import utils @@ -57,7 +53,7 @@ class CommandBootswatchTheme(Command): { 'name': 'swatch', 'short': 's', - 'default': 'slate', + 'default': '', 'type': str, 'help': 'Name of the swatch from bootswatch.com.' }, @@ -72,19 +68,19 @@ class CommandBootswatchTheme(Command): def _execute(self, options, args): """Given a swatch name and a parent theme, creates a custom theme.""" - if requests is None: - utils.req_missing(['requests'], 'install Bootswatch themes') - name = options['name'] swatch = options['swatch'] + if not swatch: + LOGGER.error('The -s option is mandatory') + return 1 parent = options['parent'] version = '' # See if we need bootswatch for bootstrap v2 or v3 themes = utils.get_theme_chain(parent) - if 'bootstrap3' not in themes or 'bootstrap3-jinja' not in themes: + if 'bootstrap3' not in themes and 'bootstrap3-jinja' not in themes: version = '2' - elif 'bootstrap' not in themes or 'bootstrap-jinja' not in themes: + elif 'bootstrap' not in themes and 'bootstrap-jinja' not in themes: LOGGER.warn('"bootswatch_theme" only makes sense for themes that use bootstrap') elif 'bootstrap3-gradients' in themes or 'bootstrap3-gradients-jinja' in themes: LOGGER.warn('"bootswatch_theme" doesn\'t work well with the bootstrap3-gradients family') diff --git a/nikola/plugins/command/check.plugin b/nikola/plugins/command/check.plugin index 8ceda5f..dd0980e 100644 --- a/nikola/plugins/command/check.plugin +++ b/nikola/plugins/command/check.plugin @@ -4,7 +4,7 @@ Module = check [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Check the generated site diff --git a/nikola/plugins/command/check.py b/nikola/plugins/command/check.py index bd254f4..a9bc44a 100644 --- a/nikola/plugins/command/check.py +++ b/nikola/plugins/command/check.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -25,6 +25,7 @@ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import print_function +from collections import defaultdict import os import re import sys @@ -34,21 +35,36 @@ try: except ImportError: from urllib.parse import unquote, urlparse, urljoin, urldefrag # NOQA +from doit.loader import generate_tasks import lxml.html +import requests from nikola.plugin_categories import Command from nikola.utils import get_logger +def _call_nikola_list(site): + files = [] + deps = defaultdict(list) + for task in generate_tasks('render_site', site.gen_tasks('render_site', "Task", '')): + files.extend(task.targets) + for target in task.targets: + deps[target].extend(task.file_dep) + for task in generate_tasks('post_render', site.gen_tasks('render_site', "LateTask", '')): + files.extend(task.targets) + for target in task.targets: + deps[target].extend(task.file_dep) + return files, deps + + def real_scan_files(site): task_fnames = set([]) real_fnames = set([]) output_folder = site.config['OUTPUT_FOLDER'] # First check that all targets are generated in the right places - for task in os.popen('nikola list --all', 'r').readlines(): - task = task.strip() - if output_folder in task and ':' in task: - fname = task.split(':', 1)[-1] + for fname in _call_nikola_list(site)[0]: + fname = fname.strip() + if fname.startswith(output_folder): task_fnames.add(fname) # And now check that there are no non-target files for root, dirs, files in os.walk(output_folder, followlinks=True): @@ -68,7 +84,7 @@ def fs_relpath_from_url_path(url_path): url_path = unquote(url_path) # in windows relative paths don't begin with os.sep if sys.platform == 'win32' and len(url_path): - url_path = url_path[1:].replace('/', '\\') + url_path = url_path.replace('/', '\\') return url_path @@ -78,7 +94,7 @@ class CommandCheck(Command): name = "check" logger = None - doc_usage = "-l [--find-sources] | -f" + doc_usage = "[-v] (-l [--find-sources] [-r] | -f [--clean-files])" doc_purpose = "check links and files in the generated site" cmd_options = [ { @@ -119,11 +135,18 @@ class CommandCheck(Command): 'default': False, 'help': 'Be more verbose.', }, + { + 'name': 'remote', + 'long': 'remote', + 'short': 'r', + 'type': bool, + 'default': False, + 'help': 'Check that remote links work.', + }, ] def _execute(self, options, args): """Check the generated site.""" - self.logger = get_logger('check', self.site.loghandlers) if not options['links'] and not options['files'] and not options['clean']: @@ -134,59 +157,103 @@ class CommandCheck(Command): else: self.logger.level = 4 if options['links']: - failure = self.scan_links(options['find_sources']) + failure = self.scan_links(options['find_sources'], options['remote']) if options['files']: failure = self.scan_files() if options['clean']: failure = self.clean_files() if failure: - sys.exit(1) + return 1 existing_targets = set([]) + checked_remote_targets = {} - def analyze(self, task, find_sources=False): + def analyze(self, fname, find_sources=False, check_remote=False): rv = False self.whitelist = [re.compile(x) for x in self.site.config['LINK_CHECK_WHITELIST']] base_url = urlparse(self.site.config['BASE_URL']) self.existing_targets.add(self.site.config['SITE_URL']) self.existing_targets.add(self.site.config['BASE_URL']) url_type = self.site.config['URL_TYPE'] - if url_type == 'absolute': - url_netloc_to_root = urlparse(self.site.config['SITE_URL']).path + + deps = {} + if find_sources: + deps = _call_nikola_list(self.site)[1] + + if url_type in ('absolute', 'full_path'): + url_netloc_to_root = urlparse(self.site.config['BASE_URL']).path try: - filename = task.split(":")[-1] - d = lxml.html.fromstring(open(filename).read()) + filename = fname + + if filename.startswith(self.site.config['CACHE_FOLDER']): + # Do not look at links in the cache, which are not parsed by + # anyone and may result in false positives. Problems arise + # with galleries, for example. Full rationale: (Issue #1447) + self.logger.notice("Ignoring {0} (in cache, links may be incorrect)".format(filename)) + return False + + if not os.path.exists(fname): + # Quietly ignore files that don’t exist; use `nikola check -f` instead (Issue #1831) + return False + + d = lxml.html.fromstring(open(filename, 'rb').read()) for l in d.iterlinks(): - target = l[0].attrib[l[1]] + target = l[2] if target == "#": continue target, _ = urldefrag(target) parsed = urlparse(target) - # Absolute links when using only paths, skip. - if (parsed.scheme or target.startswith('//')) and url_type in ('rel_path', 'full_path'): - continue + # Warn about links from https to http (mixed-security) + if base_url.netloc == parsed.netloc and base_url.scheme == "https" and parsed.scheme == "http": + self.logger.warn("Mixed-content security for link in {0}: {1}".format(filename, target)) # Absolute links to other domains, skip - if (parsed.scheme or target.startswith('//')) and parsed.netloc != base_url.netloc: + # Absolute links when using only paths, skip. + if ((parsed.scheme or target.startswith('//')) and parsed.netloc != base_url.netloc) or \ + ((parsed.scheme or target.startswith('//')) and url_type in ('rel_path', 'full_path')): + if not check_remote or parsed.scheme not in ["http", "https"]: + continue + if parsed.netloc == base_url.netloc: # absolute URL to self.site + continue + if target in self.checked_remote_targets: # already checked this exact target + if self.checked_remote_targets[target] > 399: + self.logger.warn("Broken link in {0}: {1} [Error {2}]".format(filename, target, self.checked_remote_targets[target])) + continue + # Check the remote link works + req_headers = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0 (Nikola)'} # I’m a real boy! + resp = requests.head(target, headers=req_headers) + self.checked_remote_targets[target] = resp.status_code + if resp.status_code > 399: # Error + self.logger.warn("Broken link in {0}: {1} [Error {2}]".format(filename, target, resp.status_code)) + continue + elif resp.status_code <= 399: # The address leads *somewhere* that is not an error + self.logger.debug("Successfully checked remote link in {0}: {1} [HTTP: {2}]".format(filename, target, resp.status_code)) + continue + self.logger.warn("Could not check remote link in {0}: {1} [Unknown problem]".format(filename, target)) continue if url_type == 'rel_path': - target_filename = os.path.abspath( - os.path.join(os.path.dirname(filename), unquote(target))) + if target.startswith('/'): + target_filename = os.path.abspath( + os.path.join(self.site.config['OUTPUT_FOLDER'], unquote(target.lstrip('/')))) + else: # Relative path + target_filename = os.path.abspath( + os.path.join(os.path.dirname(filename), unquote(target))) elif url_type in ('full_path', 'absolute'): if url_type == 'absolute': # convert to 'full_path' case, ie url relative to root - url_rel_path = target.path[len(url_netloc_to_root):] + url_rel_path = parsed.path[len(url_netloc_to_root):] else: - url_rel_path = target.path + # convert to relative to base path + url_rel_path = target[len(url_netloc_to_root):] if url_rel_path == '' or url_rel_path.endswith('/'): url_rel_path = urljoin(url_rel_path, self.site.config['INDEX_FILE']) fs_rel_path = fs_relpath_from_url_path(url_rel_path) target_filename = os.path.join(self.site.config['OUTPUT_FOLDER'], fs_rel_path) - if any(re.match(x, target_filename) for x in self.whitelist): + if any(re.search(x, target_filename) for x in self.whitelist): continue elif target_filename not in self.existing_targets: if os.path.exists(target_filename): @@ -197,25 +264,22 @@ class CommandCheck(Command): self.logger.warn("Broken link in {0}: {1}".format(filename, target)) if find_sources: self.logger.warn("Possible sources:") - self.logger.warn(os.popen('nikola list --deps ' + task, 'r').read()) + self.logger.warn("\n".join(deps[filename])) self.logger.warn("===============================\n") except Exception as exc: self.logger.error("Error with: {0} {1}".format(filename, exc)) return rv - def scan_links(self, find_sources=False): + def scan_links(self, find_sources=False, check_remote=False): self.logger.info("Checking Links:") self.logger.info("===============\n") self.logger.notice("{0} mode".format(self.site.config['URL_TYPE'])) failure = False - for task in os.popen('nikola list --all', 'r').readlines(): - task = task.strip() - if task.split(':')[0] in ( - 'render_tags', 'render_archive', - 'render_galleries', 'render_indexes', - 'render_pages' - 'render_site') and '.html' in task: - if self.analyze(task, find_sources): + # Maybe we should just examine all HTML files + output_folder = self.site.config['OUTPUT_FOLDER'] + for fname in _call_nikola_list(self.site)[0]: + if fname.startswith(output_folder) and '.html' == fname[-5:]: + if self.analyze(fname, find_sources, check_remote): failure = True if not failure: self.logger.info("All links checked.") diff --git a/nikola/plugins/command/console.plugin b/nikola/plugins/command/console.plugin index 2eeedae..3aef2e7 100644 --- a/nikola/plugins/command/console.plugin +++ b/nikola/plugins/command/console.plugin @@ -4,6 +4,6 @@ Module = console [Documentation] Author = Chris Warrick, Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Start a debugging python console diff --git a/nikola/plugins/command/console.py b/nikola/plugins/command/console.py index 9dfc975..b8e7825 100644 --- a/nikola/plugins/command/console.py +++ b/nikola/plugins/command/console.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Chris Warrick, Roberto Alsina and others. +# Copyright © 2012-2015 Chris Warrick, Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -30,7 +30,7 @@ import os from nikola import __version__ from nikola.plugin_categories import Command -from nikola.utils import get_logger, STDERR_HANDLER, req_missing +from nikola.utils import get_logger, STDERR_HANDLER, req_missing, Commands LOGGER = get_logger('console', STDERR_HANDLER) @@ -122,6 +122,8 @@ If there is no console to use specified (as -b, -i, -p) it tries IPython, then f self.site.scan_posts() # Create nice object with all commands: + self.site.commands = Commands(self.site.doit, self.config, self._doitargs) + self.context = { 'conf': self.site.config, 'site': self.site, diff --git a/nikola/plugins/command/deploy.plugin b/nikola/plugins/command/deploy.plugin index 10cc796..14fd53f 100644 --- a/nikola/plugins/command/deploy.plugin +++ b/nikola/plugins/command/deploy.plugin @@ -4,6 +4,6 @@ Module = deploy [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Deploy the site diff --git a/nikola/plugins/command/deploy.py b/nikola/plugins/command/deploy.py index fde43fa..2c44e87 100644 --- a/nikola/plugins/command/deploy.py +++ b/nikola/plugins/command/deploy.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -29,23 +29,22 @@ import io from datetime import datetime from dateutil.tz import gettz import os -import sys import subprocess import time from blinker import signal from nikola.plugin_categories import Command -from nikola.utils import get_logger, remove_file, unicode_str +from nikola.utils import get_logger, remove_file, unicode_str, makedirs class CommandDeploy(Command): """Deploy site.""" name = "deploy" - doc_usage = "" + doc_usage = "[[preset [preset...]]" doc_purpose = "deploy the site" - + doc_description = "Deploy the site by executing deploy commands from the presets listed on the command line. If no presets are specified, `default` is executed." logger = None def _execute(self, command, args): @@ -74,14 +73,29 @@ class CommandDeploy(Command): remove_file(os.path.join(out_dir, post.source_path)) undeployed_posts.append(post) - for command in self.site.config['DEPLOY_COMMANDS']: - self.logger.info("==> {0}".format(command)) + if args: + presets = args + else: + presets = ['default'] + + # test for preset existence + for preset in presets: try: - subprocess.check_call(command, shell=True) - except subprocess.CalledProcessError as e: - self.logger.error('Failed deployment — command {0} ' - 'returned {1}'.format(e.cmd, e.returncode)) - sys.exit(e.returncode) + self.site.config['DEPLOY_COMMANDS'][preset] + except: + self.logger.error('No such preset: {0}'.format(preset)) + return 255 + + for preset in presets: + self.logger.info("=> preset '{0}'".format(preset)) + for command in self.site.config['DEPLOY_COMMANDS'][preset]: + self.logger.info("==> {0}".format(command)) + try: + subprocess.check_call(command, shell=True) + except subprocess.CalledProcessError as e: + self.logger.error('Failed deployment — command {0} ' + 'returned {1}'.format(e.cmd, e.returncode)) + return e.returncode self.logger.info("Successful deployment") try: @@ -96,6 +110,7 @@ class CommandDeploy(Command): new_deploy = datetime.utcnow() self._emit_deploy_event(last_deploy, new_deploy, clean, undeployed_posts) + makedirs(self.site.config['CACHE_FOLDER']) # Store timestamp of successful deployment with io.open(timestamp_path, 'w+', encoding='utf8') as outf: outf.write(unicode_str(new_deploy.isoformat())) diff --git a/nikola/plugins/command/github_deploy.plugin b/nikola/plugins/command/github_deploy.plugin index 4cbc422..74e7902 100644 --- a/nikola/plugins/command/github_deploy.plugin +++ b/nikola/plugins/command/github_deploy.plugin @@ -4,6 +4,6 @@ Module = github_deploy [Documentation] Author = Puneeth Chaganti -Version = 0.1 +Version = 1,0 Website = http://getnikola.com Description = Deploy the site to GitHub pages. diff --git a/nikola/plugins/command/github_deploy.py b/nikola/plugins/command/github_deploy.py index 13da48c..888a4f9 100644 --- a/nikola/plugins/command/github_deploy.py +++ b/nikola/plugins/command/github_deploy.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2014 Puneeth Chaganti and others. +# Copyright © 2014-2015 Puneeth Chaganti and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -25,15 +25,15 @@ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import print_function +from datetime import datetime +import io import os -import shutil import subprocess -import sys from textwrap import dedent from nikola.plugin_categories import Command from nikola.plugins.command.check import real_scan_files -from nikola.utils import ask_yesno, get_logger +from nikola.utils import get_logger, req_missing, makedirs, unicode_str from nikola.__main__ import main from nikola import __version__ @@ -43,79 +43,53 @@ def uni_check_output(*args, **kwargs): return o.decode('utf-8') +def check_ghp_import_installed(): + try: + subprocess.check_output(['ghp-import', '-h']) + except OSError: + # req_missing defaults to `python=True` — and it’s meant to be like this. + # `ghp-import` is installed via pip, but the only way to use it is by executing the script it installs. + req_missing(['ghp-import'], 'deploy the site to GitHub Pages') + + class CommandGitHubDeploy(Command): - """ Deploy site to GitHub pages. """ + """ Deploy site to GitHub Pages. """ name = 'github_deploy' doc_usage = '' - doc_purpose = 'deploy the site to GitHub pages' + doc_purpose = 'deploy the site to GitHub Pages' doc_description = dedent( """\ - This command can be used to deploy your site to GitHub pages. - It performs the following actions: + This command can be used to deploy your site to GitHub Pages. - 1. Ensure that your site is a git repository, and git is on the PATH. - 2. Ensure that the output directory is not committed on the - source branch. - 3. Check for changes, and prompt the user to continue, if required. - 4. Build the site - 5. Clean any files that are "unknown" to Nikola. - 6. Create a deploy branch, if one doesn't exist. - 7. Commit the output to this branch. (NOTE: Any untracked source - files, may get committed at this stage, on the wrong branch!) - 8. Push and deploy! + It uses ghp-import to do this task. - NOTE: This command needs your site to be a git repository, with a - master branch (or a different branch, configured using - GITHUB_SOURCE_BRANCH if you are pushing to user.github - .io/organization.github.io pages) containing the sources of your - site. You also, obviously, need to have `git` on your PATH, - and should be able to push to the repository specified as the remote - (origin, by default). """ ) logger = None - _deploy_branch = '' - _source_branch = '' - _remote_name = '' - def _execute(self, command, args): self.logger = get_logger( CommandGitHubDeploy.name, self.site.loghandlers ) - self._source_branch = self.site.config.get( - 'GITHUB_SOURCE_BRANCH', 'master' - ) - self._deploy_branch = self.site.config.get( - 'GITHUB_DEPLOY_BRANCH', 'gh-pages' - ) - self._remote_name = self.site.config.get( - 'GITHUB_REMOTE_NAME', 'origin' - ) - - self._ensure_git_repo() - - self._exit_if_output_committed() - if not self._prompt_continue(): - return + # Check if ghp-import is installed + check_ghp_import_installed() + # Build before deploying build = main(['build']) if build != 0: self.logger.error('Build failed, not deploying to GitHub') - sys.exit(build) + return build + # Clean non-target files only_on_output, _ = real_scan_files(self.site) for f in only_on_output: os.unlink(f) - self._checkout_deploy_branch() - - self._copy_output() - + # Commit and push self._commit_and_push() return @@ -123,150 +97,34 @@ class CommandGitHubDeploy(Command): def _commit_and_push(self): """ Commit all the files and push. """ - deploy = self._deploy_branch - source = self._source_branch - remote = self._remote_name - + source = self.site.config['GITHUB_SOURCE_BRANCH'] + deploy = self.site.config['GITHUB_DEPLOY_BRANCH'] + remote = self.site.config['GITHUB_REMOTE_NAME'] source_commit = uni_check_output(['git', 'rev-parse', source]) commit_message = ( 'Nikola auto commit.\n\n' 'Source commit: %s' 'Nikola version: %s' % (source_commit, __version__) ) - - commands = [ - ['git', 'pull', remote, '%s:%s' % (deploy, deploy)], - ['git', 'add', '-A'], - ['git', 'commit', '-m', commit_message], - ['git', 'push', remote, '%s:%s' % (deploy, deploy)], - ['git', 'checkout', source], - ] - - for command in commands: - self.logger.info("==> {0}".format(command)) - try: - subprocess.check_call(command) - except subprocess.CalledProcessError as e: - self.logger.error( - 'Failed GitHub deployment — command {0} ' - 'returned {1}'.format(e.cmd, e.returncode) - ) - sys.exit(e.returncode) - - def _copy_output(self): - """ Copy all output to the top level directory. """ output_folder = self.site.config['OUTPUT_FOLDER'] - for each in os.listdir(output_folder): - if os.path.exists(each): - if os.path.isdir(each): - shutil.rmtree(each) - - else: - os.unlink(each) - - shutil.move(os.path.join(output_folder, each), '.') - - def _checkout_deploy_branch(self): - """ Check out the deploy branch - - Creates an orphan branch if not present. - - """ - deploy = self._deploy_branch + command = ['ghp-import', '-n', '-m', commit_message, '-p', '-r', remote, '-b', deploy, output_folder] + self.logger.info("==> {0}".format(command)) try: - subprocess.check_call( - [ - 'git', 'show-ref', '--verify', '--quiet', - 'refs/heads/%s' % deploy - ] - ) - except subprocess.CalledProcessError: - self._create_orphan_deploy_branch() - else: - subprocess.check_call(['git', 'checkout', deploy]) - - def _create_orphan_deploy_branch(self): - """ Create an orphan deploy branch """ - - result = subprocess.check_call( - ['git', 'checkout', '--orphan', self._deploy_branch] - ) - if result != 0: - self.logger.error('Failed to create a deploy branch') - sys.exit(1) - - result = subprocess.check_call(['git', 'rm', '-rf', '.']) - if result != 0: - self.logger.error('Failed to create a deploy branch') - sys.exit(1) - - with open('.gitignore', 'w') as f: - f.write('%s\n' % self.site.config['OUTPUT_FOLDER']) - f.write('%s\n' % self.site.config['CACHE_FOLDER']) - f.write('*.pyc\n') - f.write('*.db\n') - - subprocess.check_call(['git', 'add', '.gitignore']) - subprocess.check_call(['git', 'commit', '-m', 'Add .gitignore']) - - def _ensure_git_repo(self): - """ Ensure that the site is a git-repo. - - Also make sure that a remote with the specified name exists. - - """ - - try: - remotes = uni_check_output(['git', 'remote']) + subprocess.check_call(command) except subprocess.CalledProcessError as e: - self.logger.notice('github_deploy needs a git repository!') - sys.exit(e.returncode) - except OSError as e: - import errno - self.logger.error('Running git failed with {0}'.format(e)) - if e.errno == errno.ENOENT: - self.logger.notice('Is git on the PATH?') - sys.exit(1) - else: - if self._remote_name not in remotes: - self.logger.error( - 'Need a remote called "%s" configured' % self._remote_name - ) - sys.exit(1) - - def _exit_if_output_committed(self): - """ Exit if the output folder is committed on the source branch. """ - - source = self._source_branch - subprocess.check_call(['git', 'checkout', source]) - - output_folder = self.site.config['OUTPUT_FOLDER'] - output_log = uni_check_output( - ['git', 'ls-files', '--', output_folder] - ) - - if len(output_log.strip()) > 0: self.logger.error( - 'Output folder is committed on the source branch. ' - 'Cannot proceed until it is removed.' + 'Failed GitHub deployment — command {0} ' + 'returned {1}'.format(e.cmd, e.returncode) ) - sys.exit(1) - - def _prompt_continue(self): - """ Show uncommitted changes, and ask if user wants to continue. """ + return e.returncode - changes = uni_check_output(['git', 'status', '--porcelain']) - if changes.strip(): - changes = uni_check_output(['git', 'status']).strip() - message = ( - "You have the following changes:\n%s\n\n" - "Anything not committed, and unknown to Nikola may be lost, " - "or committed onto the wrong branch. Do you wish to continue?" - ) % changes - proceed = ask_yesno(message, False) - else: - proceed = True + self.logger.info("Successful deployment") - return proceed + # Store timestamp of successful deployment + timestamp_path = os.path.join(self.site.config["CACHE_FOLDER"], "lastdeploy") + new_deploy = datetime.utcnow() + makedirs(self.site.config["CACHE_FOLDER"]) + with io.open(timestamp_path, "w+", encoding="utf8") as outf: + outf.write(unicode_str(new_deploy.isoformat())) diff --git a/nikola/plugins/command/import_wordpress.plugin b/nikola/plugins/command/import_wordpress.plugin index fadc759..e072224 100644 --- a/nikola/plugins/command/import_wordpress.plugin +++ b/nikola/plugins/command/import_wordpress.plugin @@ -4,7 +4,7 @@ Module = import_wordpress [Documentation] Author = Roberto Alsina -Version = 0.2 +Version = 1.0 Website = http://getnikola.com Description = Import a wordpress site from a XML dump (requires markdown). diff --git a/nikola/plugins/command/import_wordpress.py b/nikola/plugins/command/import_wordpress.py index 1af4083..674fc2a 100644 --- a/nikola/plugins/command/import_wordpress.py +++ b/nikola/plugins/command/import_wordpress.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -28,6 +28,8 @@ from __future__ import unicode_literals, print_function import os import re import sys +import datetime +import requests from lxml import etree try: @@ -37,11 +39,6 @@ except ImportError: from urllib.parse import urlparse, unquote # NOQA try: - import requests -except ImportError: - requests = None # NOQA - -try: import phpserialize except ImportError: phpserialize = None # NOQA @@ -87,6 +84,13 @@ class CommandImportWordpress(Command, ImportMixin): 'help': "Do not try to download files for the import", }, { + 'name': 'download_auth', + 'long': 'download-auth', + 'default': None, + 'type': str, + 'help': "Specify username and password for HTTP authentication (separated by ':')", + }, + { 'name': 'separate_qtranslate_content', 'long': 'qtranslate', 'default': False, @@ -104,6 +108,7 @@ class CommandImportWordpress(Command, ImportMixin): 'help': "The pattern for translation files names", }, ] + all_tags = set([]) def _execute(self, options={}, args=[]): """Import a WordPress blog from an export file into a Nikola site.""" @@ -133,6 +138,14 @@ class CommandImportWordpress(Command, ImportMixin): self.exclude_drafts = options.get('exclude_drafts', False) self.no_downloads = options.get('no_downloads', False) + self.auth = None + if options.get('download_auth') is not None: + username_password = options.get('download_auth') + self.auth = tuple(username_password.split(':', 1)) + if len(self.auth) < 2: + print("Please specify HTTP authentication credentials in the form username:password.") + return False + self.separate_qtranslate_content = options.get('separate_qtranslate_content') self.translations_pattern = options.get('translations_pattern') @@ -149,11 +162,7 @@ class CommandImportWordpress(Command, ImportMixin): package=modulename) ) - if requests is None and phpserialize is None: - req_missing(['requests', 'phpserialize'], 'import WordPress dumps without --no-downloads') - elif requests is None: - req_missing(['requests'], 'import WordPress dumps without --no-downloads') - elif phpserialize is None: + if phpserialize is None: req_missing(['phpserialize'], 'import WordPress dumps without --no-downloads') channel = self.get_channel_from_file(self.wordpress_export_file) @@ -172,6 +181,19 @@ class CommandImportWordpress(Command, ImportMixin): self.extra_languages) self.context['REDIRECTIONS'] = self.configure_redirections( self.url_map) + + # Add tag redirects + for tag in self.all_tags: + try: + tag_str = tag.decode('utf8') + except AttributeError: + tag_str = tag + tag = utils.slugify(tag_str) + src_url = '{}tag/{}'.format(self.context['SITE_URL'], tag) + dst_url = self.site.link('tag', tag) + if src_url != dst_url: + self.url_map[src_url] = dst_url + self.write_urlmap_csv( os.path.join(self.output_folder, 'url_map.csv'), self.url_map) rendered_template = conf_template.render(**prepare_config(self.context)) @@ -186,26 +208,6 @@ class CommandImportWordpress(Command, ImportMixin): rendered_template) @classmethod - def _glue_xml_lines(cls, xml): - new_xml = xml[0] - previous_line_ended_in_newline = new_xml.endswith(b'\n') - previous_line_was_indentet = False - for line in xml[1:]: - if (re.match(b'^[ \t]+', line) and previous_line_ended_in_newline): - new_xml = b''.join((new_xml, line)) - previous_line_was_indentet = True - elif previous_line_was_indentet: - new_xml = b''.join((new_xml, line)) - previous_line_was_indentet = False - else: - new_xml = b'\n'.join((new_xml, line)) - previous_line_was_indentet = False - - previous_line_ended_in_newline = line.endswith(b'\n') - - return new_xml - - @classmethod def read_xml_file(cls, filename): xml = [] @@ -215,8 +217,7 @@ class CommandImportWordpress(Command, ImportMixin): if b'<atom:link rel=' in line: continue xml.append(line) - - return cls._glue_xml_lines(xml) + return b'\n'.join(xml) @classmethod def get_channel_from_file(cls, filename): @@ -255,9 +256,15 @@ class CommandImportWordpress(Command, ImportMixin): '{{{0}}}author_display_name'.format(wordpress_namespace), "Joe Example") context['POSTS'] = '''( + ("posts/*.rst", "posts", "post.tmpl"), + ("posts/*.txt", "posts", "post.tmpl"), + ("posts/*.md", "posts", "post.tmpl"), ("posts/*.wp", "posts", "post.tmpl"), )''' context['PAGES'] = '''( + ("stories/*.rst", "stories", "story.tmpl"), + ("stories/*.txt", "stories", "story.tmpl"), + ("stories/*.md", "stories", "story.tmpl"), ("stories/*.wp", "stories", "story.tmpl"), )''' context['COMPILERS'] = '''{ @@ -274,8 +281,12 @@ class CommandImportWordpress(Command, ImportMixin): return try: + request = requests.get(url, auth=self.auth) + if request.status_code >= 400: + LOGGER.warn("Downloading {0} to {1} failed with HTTP status code {2}".format(url, dst_path, request.status_code)) + return with open(dst_path, 'wb+') as fd: - fd.write(requests.get(url).content) + fd.write(request.content) except requests.exceptions.ConnectionError as err: LOGGER.warn("Downloading {0} to {1} failed: {2}".format(url, dst_path, err)) @@ -285,8 +296,7 @@ class CommandImportWordpress(Command, ImportMixin): link = get_text_tag(item, '{{{0}}}link'.format(wordpress_namespace), 'foo') path = urlparse(url).path - dst_path = os.path.join(*([self.output_folder, 'files'] - + list(path.split('/')))) + dst_path = os.path.join(*([self.output_folder, 'files'] + list(path.split('/')))) dst_dir = os.path.dirname(dst_path) utils.makedirs(dst_dir) LOGGER.info("Downloading {0} => {1}".format(url, dst_path)) @@ -306,7 +316,6 @@ class CommandImportWordpress(Command, ImportMixin): return additional_metadata = item.findall('{{{0}}}postmeta'.format(wordpress_namespace)) - if additional_metadata is None: return @@ -341,8 +350,7 @@ class CommandImportWordpress(Command, ImportMixin): url = '/'.join([source_path, filename.decode('utf-8')]) path = urlparse(url).path - dst_path = os.path.join(*([self.output_folder, 'files'] - + list(path.split('/')))) + dst_path = os.path.join(*([self.output_folder, 'files'] + list(path.split('/')))) dst_dir = os.path.dirname(dst_path) utils.makedirs(dst_dir) LOGGER.info("Downloading {0} => {1}".format(url, dst_path)) @@ -351,13 +359,34 @@ class CommandImportWordpress(Command, ImportMixin): links[url] = '/' + dst_url links[url] = '/' + dst_url - @staticmethod - def transform_sourcecode(content): - new_content = re.sub('\[sourcecode language="([^"]+)"\]', - "\n~~~~~~~~~~~~{.\\1}\n", content) - new_content = new_content.replace('[/sourcecode]', - "\n~~~~~~~~~~~~\n") - return new_content + code_re1 = re.compile(r'\[code.* lang.*?="(.*?)?".*\](.*?)\[/code\]', re.DOTALL | re.MULTILINE) + code_re2 = re.compile(r'\[sourcecode.* lang.*?="(.*?)?".*\](.*?)\[/sourcecode\]', re.DOTALL | re.MULTILINE) + code_re3 = re.compile(r'\[code.*?\](.*?)\[/code\]', re.DOTALL | re.MULTILINE) + code_re4 = re.compile(r'\[sourcecode.*?\](.*?)\[/sourcecode\]', re.DOTALL | re.MULTILINE) + + def transform_code(self, content): + # http://en.support.wordpress.com/code/posting-source-code/. There are + # a ton of things not supported here. We only do a basic [code + # lang="x"] -> ```x translation, and remove quoted html entities (<, + # >, &, and "). + def replacement(m, c=content): + if len(m.groups()) == 1: + language = '' + code = m.group(0) + else: + language = m.group(1) or '' + code = m.group(2) + code = code.replace('&', '&') + code = code.replace('>', '>') + code = code.replace('<', '<') + code = code.replace('"', '"') + return '```{language}\n{code}\n```'.format(language=language, code=code) + + content = self.code_re1.sub(replacement, content) + content = self.code_re2.sub(replacement, content) + content = self.code_re3.sub(replacement, content) + content = self.code_re4.sub(replacement, content) + return content @staticmethod def transform_caption(content): @@ -374,10 +403,10 @@ class CommandImportWordpress(Command, ImportMixin): return content def transform_content(self, content): - new_content = self.transform_sourcecode(content) - new_content = self.transform_caption(new_content) - new_content = self.transform_multiple_newlines(new_content) - return new_content + content = self.transform_code(content) + content = self.transform_caption(content) + content = self.transform_multiple_newlines(content) + return content def import_item(self, item, wordpress_namespace, out_folder=None): """Takes an item from the feed and creates a post file.""" @@ -391,11 +420,10 @@ class CommandImportWordpress(Command, ImportMixin): parsed = urlparse(link) path = unquote(parsed.path.strip('/')) - # In python 2, path is a str. slug requires a unicode - # object. According to wikipedia, unquoted strings will - # usually be UTF8 - if isinstance(path, utils.bytes_str): + try: path = path.decode('utf8') + except AttributeError: + pass # Cut out the base directory. if path.startswith(self.base_dir.strip('/')): @@ -420,7 +448,13 @@ class CommandImportWordpress(Command, ImportMixin): description = get_text_tag(item, 'description', '') post_date = get_text_tag( item, '{{{0}}}post_date'.format(wordpress_namespace), None) - dt = utils.to_datetime(post_date) + try: + dt = utils.to_datetime(post_date) + except ValueError: + dt = datetime.datetime(1970, 1, 1, 0, 0, 0) + LOGGER.error('Malformed date "{0}" in "{1}" [{2}], assuming 1970-01-01 00:00:00 instead.'.format(post_date, title, slug)) + post_date = dt.strftime('%Y-%m-%d %H:%M:%S') + if dt.tzinfo and self.timezone is None: self.timezone = utils.get_tzname(dt) status = get_text_tag( @@ -443,12 +477,20 @@ class CommandImportWordpress(Command, ImportMixin): if text == 'Uncategorized': continue tags.append(text) + self.all_tags.add(text) if '$latex' in content: tags.append('mathjax') + # Find post format if it's there + post_format = 'wp' + format_tag = [x for x in item.findall('*//{%s}meta_key' % wordpress_namespace) if x.text == '_tc_post_format'] + if format_tag: + post_format = format_tag[0].getparent().find('{%s}meta_value' % wordpress_namespace).text + if is_draft and self.exclude_drafts: LOGGER.notice('Draft "{0}" will not be imported.'.format(title)) + elif content.strip(): # If no content is found, no files are written. self.url_map[link] = (self.context['SITE_URL'] + @@ -475,7 +517,8 @@ class CommandImportWordpress(Command, ImportMixin): out_meta_filename = slug + '.meta' out_content_filename = slug + '.wp' meta_slug = slug - content = self.transform_content(content) + if post_format == 'wp': + content = self.transform_content(content) self.write_metadata(os.path.join(self.output_folder, out_folder, out_meta_filename), title, meta_slug, post_date, description, tags) @@ -510,7 +553,7 @@ def get_text_tag(tag, name, default): if tag is None: return default t = tag.find(name) - if t is not None: + if t is not None and t.text is not None: return t.text else: return default diff --git a/nikola/plugins/command/init.plugin b/nikola/plugins/command/init.plugin index a539f51..850dba9 100644 --- a/nikola/plugins/command/init.plugin +++ b/nikola/plugins/command/init.plugin @@ -4,6 +4,6 @@ Module = init [Documentation] Author = Roberto Alsina -Version = 0.2 +Version = 1.0 Website = http://getnikola.com Description = Create a new site. diff --git a/nikola/plugins/command/init.py b/nikola/plugins/command/init.py index a8b60db..7a36894 100644 --- a/nikola/plugins/command/init.py +++ b/nikola/plugins/command/init.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -33,11 +33,13 @@ import textwrap import datetime import unidecode import dateutil.tz +import dateutil.zoneinfo from mako.template import Template from pkg_resources import resource_filename +import tarfile import nikola -from nikola.nikola import DEFAULT_TRANSLATIONS_PATTERN, DEFAULT_INDEX_READ_MORE_LINK, DEFAULT_RSS_READ_MORE_LINK, LEGAL_VALUES +from nikola.nikola import DEFAULT_TRANSLATIONS_PATTERN, DEFAULT_INDEX_READ_MORE_LINK, DEFAULT_RSS_READ_MORE_LINK, LEGAL_VALUES, urlsplit, urlunsplit from nikola.plugin_categories import Command from nikola.utils import ask, ask_yesno, get_logger, makedirs, STDERR_HANDLER, load_messages from nikola.packages.tzlocal import get_localzone @@ -48,9 +50,10 @@ LOGGER = get_logger('init', STDERR_HANDLER) SAMPLE_CONF = { 'BLOG_AUTHOR': "Your Name", 'BLOG_TITLE': "Demo Site", - 'SITE_URL': "http://getnikola.com/", + 'SITE_URL': "https://example.com/", 'BLOG_EMAIL': "joe@demo.site", 'BLOG_DESCRIPTION': "This is a demo site for Nikola.", + 'PRETTY_URLS': False, 'DEFAULT_LANG': "en", 'TRANSLATIONS': """{ DEFAULT_LANG: "", @@ -186,7 +189,7 @@ def format_navigation_links(additional_languages, default_lang, messages): pairs.append(f.format('DEFAULT_LANG', '', get_msg(default_lang))) for l in additional_languages: - pairs.append(f.format(json.dumps(l), '/' + l, get_msg(l))) + pairs.append(f.format(json.dumps(l, ensure_ascii=False), '/' + l, get_msg(l))) return u'{{\n{0}\n}}'.format('\n\n'.join(pairs)) @@ -196,11 +199,13 @@ def format_navigation_links(additional_languages, default_lang, messages): def prepare_config(config): """Parse sample config with JSON.""" p = config.copy() - p.update(dict((k, json.dumps(v)) for k, v in p.items() - if k not in ('POSTS', 'PAGES', 'COMPILERS', 'TRANSLATIONS', 'NAVIGATION_LINKS', '_SUPPORTED_LANGUAGES', '_SUPPORTED_COMMENT_SYSTEMS', 'INDEX_READ_MORE_LINK', 'RSS_READ_MORE_LINK'))) + p.update(dict((k, json.dumps(v, ensure_ascii=False)) for k, v in p.items() + if k not in ('POSTS', 'PAGES', 'COMPILERS', 'TRANSLATIONS', 'NAVIGATION_LINKS', '_SUPPORTED_LANGUAGES', '_SUPPORTED_COMMENT_SYSTEMS', 'INDEX_READ_MORE_LINK', 'RSS_READ_MORE_LINK', 'PRETTY_URLS'))) # READ_MORE_LINKs require some special treatment. p['INDEX_READ_MORE_LINK'] = "'" + p['INDEX_READ_MORE_LINK'].replace("'", "\\'") + "'" p['RSS_READ_MORE_LINK'] = "'" + p['RSS_READ_MORE_LINK'].replace("'", "\\'") + "'" + # json would make that `true` instead of `True` + p['PRETTY_URLS'] = str(p['PRETTY_URLS']) return p @@ -237,14 +242,20 @@ class CommandInit(Command): src = resource_filename('nikola', os.path.join('data', 'samplesite')) shutil.copytree(src, target) - @classmethod - def create_configuration(cls, target): + @staticmethod + def create_configuration(target): template_path = resource_filename('nikola', 'conf.py.in') conf_template = Template(filename=template_path) conf_path = os.path.join(target, 'conf.py') with io.open(conf_path, 'w+', encoding='utf8') as fd: fd.write(conf_template.render(**prepare_config(SAMPLE_CONF))) + @staticmethod + def create_configuration_to_string(): + template_path = resource_filename('nikola', 'conf.py.in') + conf_template = Template(filename=template_path) + return conf_template.render(**prepare_config(SAMPLE_CONF)) + @classmethod def create_empty_site(cls, target): for folder in ('files', 'galleries', 'listings', 'posts', 'stories'): @@ -253,6 +264,39 @@ class CommandInit(Command): @staticmethod def ask_questions(target): """Ask some questions about Nikola.""" + def urlhandler(default, toconf): + answer = ask('Site URL', 'https://example.com/') + try: + answer = answer.decode('utf-8') + except (AttributeError, UnicodeDecodeError): + pass + if not answer.startswith(u'http'): + print(" ERROR: You must specify a protocol (http or https).") + urlhandler(default, toconf) + return + if not answer.endswith('/'): + print(" The URL does not end in '/' -- adding it.") + answer += '/' + + dst_url = urlsplit(answer) + try: + dst_url.netloc.encode('ascii') + except (UnicodeEncodeError, UnicodeDecodeError): + # The IDN contains characters beyond ASCII. We must convert it + # to Punycode. (Issue #1644) + nl = dst_url.netloc.encode('idna') + answer = urlunsplit((dst_url.scheme, + nl, + dst_url.path, + dst_url.query, + dst_url.fragment)) + print(" Converting to Punycode:", answer) + + SAMPLE_CONF['SITE_URL'] = answer + + def prettyhandler(default, toconf): + SAMPLE_CONF['PRETTY_URLS'] = ask_yesno('Enable pretty URLs (/page/ instead of /page.html) that don’t need web server configuration?', default=True) + def lhandler(default, toconf, show_header=True): if show_header: print("We will now ask you to provide the list of languages you want to use.") @@ -297,7 +341,7 @@ class CommandInit(Command): lhandler(default, toconf, show_header=False) def tzhandler(default, toconf): - print("\nPlease choose the correct time zone for your blog. Nikola uses the tz database.") + print("\nPlease choose the correct time zone for your blog. Nikola uses the tz database.") print("You can find your time zone here:") print("http://en.wikipedia.org/wiki/List_of_tz_database_time_zones") print("") @@ -309,12 +353,26 @@ class CommandInit(Command): lz = None answer = ask('Time zone', lz if lz else "UTC") tz = dateutil.tz.gettz(answer) + + if tz is None: + print(" WARNING: Time zone not found. Searching list of time zones for a match.") + zonesfile = tarfile.open(fileobj=dateutil.zoneinfo.getzoneinfofile_stream()) + zonenames = [zone for zone in zonesfile.getnames() if answer.lower() in zone.lower()] + if len(zonenames) == 1: + tz = dateutil.tz.gettz(zonenames[0]) + answer = zonenames[0] + print(" Picking '{0}'.".format(answer)) + elif len(zonenames) > 1: + print(" The following time zones match your query:") + print(' ' + '\n '.join(zonenames)) + continue + if tz is not None: time = datetime.datetime.now(tz).strftime('%H:%M:%S') print(" Current time in {0}: {1}".format(answer, time)) answered = ask_yesno("Use this time zone?", True) else: - print(" ERROR: Time zone not found. Please try again. Time zones are case-sensitive.") + print(" ERROR: No matches found. Please try again.") SAMPLE_CONF['TIMEZONE'] = answer @@ -353,7 +411,8 @@ class CommandInit(Command): ('Site author', 'Nikola Tesla', True, 'BLOG_AUTHOR'), ('Site author\'s e-mail', 'n.tesla@example.com', True, 'BLOG_EMAIL'), ('Site description', 'This is a demo site for Nikola.', True, 'BLOG_DESCRIPTION'), - ('Site URL', 'http://getnikola.com/', True, 'SITE_URL'), + (urlhandler, None, True, True), + (prettyhandler, None, True, True), ('Questions about languages and locales', None, None, None), (lhandler, None, True, True), (tzhandler, None, True, True), @@ -377,6 +436,10 @@ class CommandInit(Command): query(default, toconf) else: answer = ask(query, default) + try: + answer = answer.decode('utf-8') + except (AttributeError, UnicodeDecodeError): + pass if toconf: SAMPLE_CONF[destination] = answer if destination == '!target': @@ -386,7 +449,7 @@ class CommandInit(Command): STORAGE['target'] = answer print("\nThat's it, Nikola is now configured. Make sure to edit conf.py to your liking.") - print("If you are looking for themes and addons, check out http://themes.getnikola.com/ and http://plugins.getnikola.com/.") + print("If you are looking for themes and addons, check out https://themes.getnikola.com/ and https://plugins.getnikola.com/.") print("Have fun!") return STORAGE diff --git a/nikola/plugins/command/install_theme.plugin b/nikola/plugins/command/install_theme.plugin index 84b2623..54a91ff 100644 --- a/nikola/plugins/command/install_theme.plugin +++ b/nikola/plugins/command/install_theme.plugin @@ -4,7 +4,7 @@ Module = install_theme [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Install a theme into the current site. diff --git a/nikola/plugins/command/install_theme.py b/nikola/plugins/command/install_theme.py index 5397772..4937509 100644 --- a/nikola/plugins/command/install_theme.py +++ b/nikola/plugins/command/install_theme.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -28,42 +28,18 @@ from __future__ import print_function import os import io import json -import shutil +import requests import pygments from pygments.lexers import PythonLexer from pygments.formatters import TerminalFormatter -try: - import requests -except ImportError: - requests = None # NOQA - from nikola.plugin_categories import Command from nikola import utils LOGGER = utils.get_logger('install_theme', utils.STDERR_HANDLER) -# Stolen from textwrap in Python 3.3.2. -def indent(text, prefix, predicate=None): # NOQA - """Adds 'prefix' to the beginning of selected lines in 'text'. - - If 'predicate' is provided, 'prefix' will only be added to the lines - where 'predicate(line)' is True. If 'predicate' is not provided, - it will default to adding 'prefix' to all non-empty lines that do not - consist solely of whitespace characters. - """ - if predicate is None: - def predicate(line): - return line.strip() - - def prefixed_lines(): - for line in text.splitlines(True): - yield (prefix + line if predicate(line) else line) - return ''.join(prefixed_lines()) - - class CommandInstallTheme(Command): """Install a theme.""" @@ -86,16 +62,21 @@ class CommandInstallTheme(Command): 'long': 'url', 'type': str, 'help': "URL for the theme repository (default: " - "http://themes.getnikola.com/v7/themes.json)", - 'default': 'http://themes.getnikola.com/v7/themes.json' + "https://themes.getnikola.com/v7/themes.json)", + 'default': 'https://themes.getnikola.com/v7/themes.json' + }, + { + 'name': 'getpath', + 'short': 'g', + 'long': 'get-path', + 'type': bool, + 'default': False, + 'help': "Print the path for installed theme", }, ] def _execute(self, options, args): """Install theme into current site.""" - if requests is None: - utils.req_missing(['requests'], 'install themes') - listing = options['list'] url = options['url'] if args: @@ -103,6 +84,14 @@ class CommandInstallTheme(Command): else: name = None + if options['getpath'] and name: + path = utils.get_theme_path(name) + if path: + print(path) + else: + print('not installed') + return 0 + if name is None and not listing: LOGGER.error("This command needs either a theme name or the -l option.") return False @@ -135,36 +124,31 @@ class CommandInstallTheme(Command): def do_install(self, name, data): if name in data: utils.makedirs(self.output_dir) - LOGGER.info('Downloading: ' + data[name]) + LOGGER.info("Downloading '{0}'".format(data[name])) zip_file = io.BytesIO() zip_file.write(requests.get(data[name]).content) - LOGGER.info('Extracting: {0} into themes'.format(name)) + LOGGER.info("Extracting '{0}' into themes/".format(name)) utils.extract_all(zip_file) - dest_path = os.path.join('themes', name) + dest_path = os.path.join(self.output_dir, name) else: + dest_path = os.path.join(self.output_dir, name) try: theme_path = utils.get_theme_path(name) - except: - LOGGER.error("Can't find theme " + name) - return False + LOGGER.error("Theme '{0}' is already installed in {1}".format(name, theme_path)) + except Exception: + LOGGER.error("Can't find theme {0}".format(name)) - utils.makedirs(self.output_dir) - dest_path = os.path.join(self.output_dir, name) - if os.path.exists(dest_path): - LOGGER.error("{0} is already installed".format(name)) - return False + return False - LOGGER.info('Copying {0} into themes'.format(theme_path)) - shutil.copytree(theme_path, dest_path) confpypath = os.path.join(dest_path, 'conf.py.sample') if os.path.exists(confpypath): LOGGER.notice('This theme has a sample config file. Integrate it with yours in order to make this theme work!') print('Contents of the conf.py.sample file:\n') with io.open(confpypath, 'r', encoding='utf-8') as fh: if self.site.colorful: - print(indent(pygments.highlight( + print(utils.indent(pygments.highlight( fh.read(), PythonLexer(), TerminalFormatter()), 4 * ' ')) else: - print(indent(fh.read(), 4 * ' ')) + print(utils.indent(fh.read(), 4 * ' ')) return True diff --git a/nikola/plugins/command/new_page.plugin b/nikola/plugins/command/new_page.plugin index 1f1c84c..f078dd6 100644 --- a/nikola/plugins/command/new_page.plugin +++ b/nikola/plugins/command/new_page.plugin @@ -4,6 +4,6 @@ Module = new_page [Documentation] Author = Roberto Alsina, Chris Warrick -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Create a new page. diff --git a/nikola/plugins/command/new_page.py b/nikola/plugins/command/new_page.py index f07ba39..39a85bd 100644 --- a/nikola/plugins/command/new_page.py +++ b/nikola/plugins/command/new_page.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina, Chris Warrick and others. +# Copyright © 2012-2015 Roberto Alsina, Chris Warrick and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -45,6 +45,14 @@ class CommandNewPage(Command): 'help': 'Title for the page.' }, { + 'name': 'author', + 'short': 'a', + 'long': 'author', + 'type': str, + 'default': '', + 'help': 'Author of the post.' + }, + { 'name': 'onefile', 'short': '1', 'type': bool, @@ -71,13 +79,29 @@ class CommandNewPage(Command): 'long': 'format', 'type': str, 'default': '', - 'help': 'Markup format for the page, one of rest, markdown, wiki, ' - 'bbcode, html, textile, txt2tags', + 'help': 'Markup format for the page (use --available-formats for list)', + }, + { + 'name': 'available-formats', + 'short': 'F', + 'long': 'available-formats', + 'type': bool, + 'default': False, + 'help': 'List all available input formats' + }, + { + 'name': 'import', + 'short': 'i', + 'long': 'import', + 'type': str, + 'default': '', + 'help': 'Import an existing file instead of creating a placeholder' }, ] def _execute(self, options, args): """Create a new page.""" + # Defaults for some values that don’t apply to pages and the is_page option (duh!) options['tags'] = '' options['schedule'] = False options['is_page'] = True diff --git a/nikola/plugins/command/new_post.plugin b/nikola/plugins/command/new_post.plugin index ec35c35..fec4b1d 100644 --- a/nikola/plugins/command/new_post.plugin +++ b/nikola/plugins/command/new_post.plugin @@ -4,7 +4,7 @@ Module = new_post [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Create a new post. diff --git a/nikola/plugins/command/new_post.py b/nikola/plugins/command/new_post.py index 24c09d0..5141c7e 100644 --- a/nikola/plugins/command/new_post.py +++ b/nikola/plugins/command/new_post.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -30,6 +30,7 @@ import datetime import os import sys import subprocess +import operator from blinker import signal import dateutil.tz @@ -37,12 +38,13 @@ import dateutil.tz from nikola.plugin_categories import Command from nikola import utils +COMPILERS_DOC_LINK = 'https://getnikola.com/handbook.html#configuring-other-input-formats' POSTLOGGER = utils.get_logger('new_post', utils.STDERR_HANDLER) PAGELOGGER = utils.get_logger('new_page', utils.STDERR_HANDLER) LOGGER = POSTLOGGER -def filter_post_pages(compiler, is_post, compilers, post_pages): +def filter_post_pages(compiler, is_post, compilers, post_pages, compiler_objs, compilers_raw): """Given a compiler ("markdown", "rest"), and whether it's meant for a post or a page, and compilers, return the correct entry from post_pages.""" @@ -51,7 +53,15 @@ def filter_post_pages(compiler, is_post, compilers, post_pages): filtered = [entry for entry in post_pages if entry[3] == is_post] # These are the extensions supported by the required format - extensions = compilers[compiler] + extensions = compilers.get(compiler) + if extensions is None: + if compiler in compiler_objs: + LOGGER.error("There is a {0} compiler available, but it's not set in your COMPILERS option.".format(compiler)) + LOGGER.info("Read more: {0}".format(COMPILERS_DOC_LINK)) + else: + LOGGER.error('Unknown format {0}'.format(compiler)) + print_compilers(compilers_raw, post_pages, compiler_objs) + return False # Throw away the post_pages with the wrong extensions filtered = [entry for entry in filtered if any([ext in entry[0] for ext in @@ -59,13 +69,77 @@ def filter_post_pages(compiler, is_post, compilers, post_pages): if not filtered: type_name = "post" if is_post else "page" - raise Exception("Can't find a way, using your configuration, to create " - "a {0} in format {1}. You may want to tweak " - "COMPILERS or {2}S in conf.py".format( - type_name, compiler, type_name.upper())) + LOGGER.error("Can't find a way, using your configuration, to create " + "a {0} in format {1}. You may want to tweak " + "COMPILERS or {2}S in conf.py".format( + type_name, compiler, type_name.upper())) + LOGGER.info("Read more: {0}".format(COMPILERS_DOC_LINK)) + + return False return filtered[0] +def print_compilers(compilers_raw, post_pages, compiler_objs): + """ + List all available compilers in a human-friendly format. + + :param compilers_raw: The compilers dict, mapping compiler names to tuples of extensions + :param post_pages: The post_pages structure + :param compilers_objs: Compiler objects + """ + + # We use compilers_raw, because the normal dict can contain + # garbage coming from the translation candidate implementation. + # Entries are in format: (name, extensions, used_in_post_pages) + parsed_compilers = {'used': [], 'unused': [], 'disabled': []} + + for compiler_name, compiler_obj in compiler_objs.items(): + fname = compiler_obj.friendly_name or compiler_name + if compiler_name not in compilers_raw: + parsed_compilers['disabled'].append((compiler_name, fname, (), False)) + else: + # stolen from filter_post_pages + extensions = compilers_raw[compiler_name] + filtered = [entry for entry in post_pages if any( + [ext in entry[0] for ext in extensions])] + if filtered: + parsed_compilers['used'].append((compiler_name, fname, extensions, True)) + else: + parsed_compilers['unused'].append((compiler_name, fname, extensions, False)) + + # Sort compilers alphabetically by name, just so it’s prettier (and + # deterministic) + parsed_compilers['used'].sort(key=operator.itemgetter(0)) + parsed_compilers['unused'].sort(key=operator.itemgetter(0)) + parsed_compilers['disabled'].sort(key=operator.itemgetter(0)) + + # We also group the compilers by status for readability. + parsed_list = parsed_compilers['used'] + parsed_compilers['unused'] + parsed_compilers['disabled'] + + print("Available input formats:\n") + + name_width = max([len(i[0]) for i in parsed_list] + [4]) # 4 == len('NAME') + fname_width = max([len(i[1]) for i in parsed_list] + [11]) # 11 == len('DESCRIPTION') + + print((' {0:<' + str(name_width) + '} {1:<' + str(fname_width) + '} EXTENSIONS\n').format('NAME', 'DESCRIPTION')) + + for name, fname, extensions, used in parsed_list: + flag = ' ' if used else '!' + flag = flag if extensions else '~' + + extensions = ', '.join(extensions) if extensions else '(disabled: not in COMPILERS)' + + print(('{flag}{name:<' + str(name_width) + '} {fname:<' + str(fname_width) + '} {extensions}').format(flag=flag, name=name, fname=fname, extensions=extensions)) + + print(""" +More compilers are available in the Plugins Index. + +Compilers marked with ! and ~ require additional configuration: + ! not in the PAGES/POSTS tuples (unused) + ~ not in the COMPILERS dict (disabled) +Read more: {0}""".format(COMPILERS_DOC_LINK)) + + def get_default_compiler(is_post, compilers, post_pages): """Given compilers and post_pages, return a reasonable default compiler for this kind of post/page. @@ -116,7 +190,7 @@ def get_date(schedule=False, rule=None, last_date=None, tz=None, iso8601=False): rrule = None # NOQA if schedule and rrule and rule: try: - rule_ = rrule.rrulestr(rule, dtstart=last_date) + rule_ = rrule.rrulestr(rule, dtstart=last_date or date) except Exception: LOGGER.error('Unable to parse rule string, using current time.') else: @@ -161,6 +235,14 @@ class CommandNewPost(Command): 'help': 'Title for the post.' }, { + 'name': 'author', + 'short': 'a', + 'long': 'author', + 'type': str, + 'default': '', + 'help': 'Author of the post.' + }, + { 'name': 'tags', 'long': 'tags', 'type': str, @@ -194,8 +276,15 @@ class CommandNewPost(Command): 'long': 'format', 'type': str, 'default': '', - 'help': 'Markup format for the post, one of rest, markdown, wiki, ' - 'bbcode, html, textile, txt2tags', + 'help': 'Markup format for the post (use --available-formats for list)', + }, + { + 'name': 'available-formats', + 'short': 'F', + 'long': 'available-formats', + 'type': bool, + 'default': False, + 'help': 'List all available input formats' }, { 'name': 'schedule', @@ -204,6 +293,14 @@ class CommandNewPost(Command): 'default': False, 'help': 'Schedule the post based on recurrence rule' }, + { + 'name': 'import', + 'short': 'i', + 'long': 'import', + 'type': str, + 'default': '', + 'help': 'Import an existing file instead of creating a placeholder' + }, ] @@ -228,9 +325,16 @@ class CommandNewPost(Command): is_post = not is_page content_type = 'page' if is_page else 'post' title = options['title'] or None + author = options['author'] or '' tags = options['tags'] onefile = options['onefile'] twofile = options['twofile'] + import_file = options['import'] + wants_available = options['available-formats'] + + if wants_available: + print_compilers(self.site.config['_COMPILERS_RAW'], self.site.config['post_pages'], self.site.compilers) + return if is_page: LOGGER = PAGELOGGER @@ -243,6 +347,10 @@ class CommandNewPost(Command): onefile = self.site.config.get('ONE_FILE_POSTS', True) content_format = options['content_format'] + content_subformat = None + + if "@" in content_format: + content_format, content_subformat = content_format.split("@") if not content_format: # Issue #400 content_format = get_default_compiler( @@ -251,7 +359,8 @@ class CommandNewPost(Command): self.site.config['post_pages']) if content_format not in compiler_names: - LOGGER.error("Unknown {0} format {1}".format(content_type, content_format)) + LOGGER.error("Unknown {0} format {1}, maybe you need to install a plugin?".format(content_type, content_format)) + print_compilers(self.site.config['_COMPILERS_RAW'], self.site.config['post_pages'], self.site.compilers) return compiler_plugin = self.site.plugin_manager.getPluginByName( content_format, "PageCompiler").plugin_object @@ -259,10 +368,19 @@ class CommandNewPost(Command): # Guess where we should put this entry = filter_post_pages(content_format, is_post, self.site.config['COMPILERS'], - self.site.config['post_pages']) + self.site.config['post_pages'], + self.site.compilers, + self.site.config['_COMPILERS_RAW']) + + if entry is False: + return 1 - print("Creating New {0}".format(content_type.title())) - print("-----------------\n") + if import_file: + print("Importing Existing {xx}".format(xx=content_type.title())) + print("-----------------------\n") + else: + print("Creating New {xx}".format(xx=content_type.title())) + print("-----------------\n") if title is not None: print("Title:", title) else: @@ -272,7 +390,7 @@ class CommandNewPost(Command): if isinstance(title, utils.bytes_str): try: title = title.decode(sys.stdin.encoding) - except AttributeError: # for tests + except (AttributeError, TypeError): # for tests title = title.decode('utf-8') title = title.strip() @@ -282,9 +400,16 @@ class CommandNewPost(Command): if isinstance(path, utils.bytes_str): try: path = path.decode(sys.stdin.encoding) - except AttributeError: # for tests + except (AttributeError, TypeError): # for tests path = path.decode('utf-8') slug = utils.slugify(os.path.splitext(os.path.basename(path))[0]) + + if isinstance(author, utils.bytes_str): + try: + author = author.decode(sys.stdin.encoding) + except (AttributeError, TypeError): # for tests + author = author.decode('utf-8') + # Calculate the date to use for the content schedule = options['schedule'] or self.site.config['SCHEDULE_ALL'] rule = self.site.config['SCHEDULE_RULE'] @@ -308,23 +433,46 @@ class CommandNewPost(Command): if not path: txt_path = os.path.join(output_path, slug + suffix) else: - txt_path = path + txt_path = os.path.join(self.site.original_cwd, path) if (not onefile and os.path.isfile(meta_path)) or \ os.path.isfile(txt_path): + + # Emit an event when a post exists + event = dict(path=txt_path) + if not onefile: # write metadata file + event['meta_path'] = meta_path + signal('existing_' + content_type).send(self, **event) + LOGGER.error("The title already exists!") - exit() + return 8 d_name = os.path.dirname(txt_path) utils.makedirs(d_name) - metadata = self.site.config['ADDITIONAL_METADATA'] + metadata = {} + if author: + metadata['author'] = author + metadata.update(self.site.config['ADDITIONAL_METADATA']) + data.update(metadata) + + # ipynb plugin needs the ipython kernel info. We get the kernel name + # from the content_subformat and pass it to the compiler in the metadata + if content_format == "ipynb" and content_subformat is not None: + metadata["ipython_kernel"] = content_subformat # Override onefile if not really supported. if not compiler_plugin.supports_onefile and onefile: onefile = False LOGGER.warn('This compiler does not support one-file posts.') - content = "Write your {0} here.".format('page' if is_page else 'post') + if import_file: + with io.open(import_file, 'r', encoding='utf-8') as fh: + content = fh.read() + else: + if is_page: + content = self.site.MESSAGES[self.site.default_lang]["Write your page here."] + else: + content = self.site.MESSAGES[self.site.default_lang]["Write your post here."] compiler_plugin.create_post( txt_path, content=content, onefile=onefile, title=title, slug=slug, date=date, tags=tags, is_page=is_page, **metadata) diff --git a/nikola/plugins/command/orphans.plugin b/nikola/plugins/command/orphans.plugin index 408578b..f491eaf 100644 --- a/nikola/plugins/command/orphans.plugin +++ b/nikola/plugins/command/orphans.plugin @@ -4,7 +4,7 @@ Module = orphans [Documentation] Author = Roberto Alsina, Chris Warrick -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = List all orphans diff --git a/nikola/plugins/command/orphans.py b/nikola/plugins/command/orphans.py index ff114b4..f550e17 100644 --- a/nikola/plugins/command/orphans.py +++ b/nikola/plugins/command/orphans.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina, Chris Warrick and others. +# Copyright © 2012-2015 Roberto Alsina, Chris Warrick and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/command/plugin.plugin b/nikola/plugins/command/plugin.plugin index d2bca92..2815caa 100644 --- a/nikola/plugins/command/plugin.plugin +++ b/nikola/plugins/command/plugin.plugin @@ -4,7 +4,7 @@ Module = plugin [Documentation] Author = Roberto Alsina and Chris Warrick -Version = 0.2 +Version = 1.0 Website = http://getnikola.com Description = Manage Nikola plugins diff --git a/nikola/plugins/command/plugin.py b/nikola/plugins/command/plugin.py index 71901b8..56eb1d7 100644 --- a/nikola/plugins/command/plugin.py +++ b/nikola/plugins/command/plugin.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -30,41 +30,18 @@ import os import shutil import subprocess import sys +import requests import pygments from pygments.lexers import PythonLexer from pygments.formatters import TerminalFormatter -try: - import requests -except ImportError: - requests = None # NOQA - from nikola.plugin_categories import Command from nikola import utils LOGGER = utils.get_logger('plugin', utils.STDERR_HANDLER) -# Stolen from textwrap in Python 3.3.2. -def indent(text, prefix, predicate=None): # NOQA - """Adds 'prefix' to the beginning of selected lines in 'text'. - - If 'predicate' is provided, 'prefix' will only be added to the lines - where 'predicate(line)' is True. If 'predicate' is not provided, - it will default to adding 'prefix' to all non-empty lines that do not - consist solely of whitespace characters. - """ - if predicate is None: - def predicate(line): - return line.strip() - - def prefixed_lines(): - for line in text.splitlines(True): - yield (prefix + line if predicate(line) else line) - return ''.join(prefixed_lines()) - - class CommandPlugin(Command): """Manage plugins.""" @@ -105,8 +82,8 @@ class CommandPlugin(Command): 'long': 'url', 'type': str, 'help': "URL for the plugin repository (default: " - "http://plugins.getnikola.com/v7/plugins.json)", - 'default': 'http://plugins.getnikola.com/v7/plugins.json' + "https://plugins.getnikola.com/v7/plugins.json)", + 'default': 'https://plugins.getnikola.com/v7/plugins.json' }, { 'name': 'user', @@ -258,7 +235,7 @@ class CommandPlugin(Command): LOGGER.error('Could not install the dependencies.') print('Contents of the requirements.txt file:\n') with io.open(reqpath, 'r', encoding='utf-8') as fh: - print(indent(fh.read(), 4 * ' ')) + print(utils.indent(fh.read(), 4 * ' ')) print('You have to install those yourself or through a ' 'package manager.') else: @@ -272,8 +249,8 @@ class CommandPlugin(Command): with io.open(reqnpypath, 'r', encoding='utf-8') as fh: for l in fh.readlines(): i, j = l.split('::') - print(indent(i.strip(), 4 * ' ')) - print(indent(j.strip(), 8 * ' ')) + print(utils.indent(i.strip(), 4 * ' ')) + print(utils.indent(j.strip(), 8 * ' ')) print() print('You have to install those yourself or through a package ' @@ -284,11 +261,11 @@ class CommandPlugin(Command): print('Contents of the conf.py.sample file:\n') with io.open(confpypath, 'r', encoding='utf-8') as fh: if self.site.colorful: - print(indent(pygments.highlight( + print(utils.indent(pygments.highlight( fh.read(), PythonLexer(), TerminalFormatter()), 4 * ' ')) else: - print(indent(fh.read(), 4 * ' ')) + print(utils.indent(fh.read(), 4 * ' ')) return True def do_uninstall(self, name): @@ -311,8 +288,6 @@ class CommandPlugin(Command): return False def get_json(self, url): - if requests is None: - utils.req_missing(['requests'], 'install or list available plugins', python=True, optional=False) if self.json is None: self.json = requests.get(url).json() return self.json diff --git a/nikola/plugins/command/rst2html.plugin b/nikola/plugins/command/rst2html.plugin new file mode 100644 index 0000000..0d0d3b0 --- /dev/null +++ b/nikola/plugins/command/rst2html.plugin @@ -0,0 +1,9 @@ +[Core] +Name = rst2html +Module = rst2html + +[Documentation] +Author = Chris Warrick +Version = 1.0 +Website = http://getnikola.com +Description = Compile reStructuredText to HTML using the Nikola architecture diff --git a/nikola/plugins/command/rst2html/__init__.py b/nikola/plugins/command/rst2html/__init__.py new file mode 100644 index 0000000..342aaeb --- /dev/null +++ b/nikola/plugins/command/rst2html/__init__.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + +# Copyright © 2015 Chris Warrick and others. + +# 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. + +from __future__ import unicode_literals, print_function + +import io +import lxml.html +from pkg_resources import resource_filename +from mako.template import Template +from nikola.plugin_categories import Command + + +class CommandRst2Html(Command): + """Compile reStructuredText to HTML, using Nikola architecture.""" + + name = "rst2html" + doc_usage = "infile" + doc_purpose = "compile reStructuredText to HTML files" + needs_config = False + + def _execute(self, options, args): + """Compile reStructuredText to standalone HTML files.""" + compiler = self.site.plugin_manager.getPluginByName('rest', 'PageCompiler').plugin_object + if len(args) != 1: + print("This command takes only one argument (input file name).") + return 2 + source = args[0] + with io.open(source, "r", encoding="utf8") as in_file: + data = in_file.read() + output, error_level, deps = compiler.compile_html_string(data, source, True) + + rstcss_path = resource_filename('nikola', 'data/themes/base/assets/css/rst.css') + with io.open(rstcss_path, "r", encoding="utf8") as fh: + rstcss = fh.read() + + template_path = resource_filename('nikola', 'plugins/command/rst2html/rst2html.tmpl') + template = Template(filename=template_path) + template_output = template.render(rstcss=rstcss, output=output) + parser = lxml.html.HTMLParser(remove_blank_text=True) + doc = lxml.html.document_fromstring(template_output, parser) + html = b'<!DOCTYPE html>\n' + lxml.html.tostring(doc, encoding='utf8', method='html', pretty_print=True) + print(html) + if error_level < 3: + return 0 + else: + return 1 diff --git a/nikola/plugins/command/rst2html/rst2html.tmpl b/nikola/plugins/command/rst2html/rst2html.tmpl new file mode 100644 index 0000000..5a892ea --- /dev/null +++ b/nikola/plugins/command/rst2html/rst2html.tmpl @@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<style class="text/css"> +${rstcss} +</style> +</head> + +<body> +${output} +</body> +</html> diff --git a/nikola/plugins/command/serve.plugin b/nikola/plugins/command/serve.plugin index e663cc6..0c1176d 100644 --- a/nikola/plugins/command/serve.plugin +++ b/nikola/plugins/command/serve.plugin @@ -4,7 +4,7 @@ Module = serve [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Start test server. diff --git a/nikola/plugins/command/serve.py b/nikola/plugins/command/serve.py index de4f6e2..0e4d01f 100644 --- a/nikola/plugins/command/serve.py +++ b/nikola/plugins/command/serve.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -26,6 +26,7 @@ from __future__ import print_function import os +import socket import webbrowser try: from BaseHTTPServer import HTTPServer @@ -38,6 +39,11 @@ from nikola.plugin_categories import Command from nikola.utils import get_logger +class IPv6Server(HTTPServer): + """An IPv6 HTTPServer.""" + address_family = socket.AF_INET6 + + class CommandServe(Command): """Start test server.""" @@ -53,7 +59,7 @@ class CommandServe(Command): 'long': 'port', 'default': 8000, 'type': int, - 'help': 'Port nummber (default: 8000)', + 'help': 'Port number (default: 8000)', }, { 'name': 'address', @@ -61,7 +67,7 @@ class CommandServe(Command): 'long': 'address', 'type': str, 'default': '', - 'help': 'Address to bind (default: 0.0.0.0 – all local interfaces)', + 'help': 'Address to bind (default: 0.0.0.0 – all local IPv4 interfaces)', }, { 'name': 'browser', @@ -70,7 +76,15 @@ class CommandServe(Command): 'type': bool, 'default': False, 'help': 'Open the test server in a web browser', - } + }, + { + 'name': 'ipv6', + 'short': '6', + 'long': 'ipv6', + 'type': bool, + 'default': False, + 'help': 'Use IPv6', + }, ) def _execute(self, options, args): @@ -81,19 +95,33 @@ class CommandServe(Command): self.logger.error("Missing '{0}' folder?".format(out_dir)) else: os.chdir(out_dir) - httpd = HTTPServer((options['address'], options['port']), - OurHTTPRequestHandler) + if '[' in options['address']: + options['address'] = options['address'].strip('[').strip(']') + ipv6 = True + OurHTTP = IPv6Server + elif options['ipv6']: + ipv6 = True + OurHTTP = IPv6Server + else: + ipv6 = False + OurHTTP = HTTPServer + + httpd = OurHTTP((options['address'], options['port']), + OurHTTPRequestHandler) sa = httpd.socket.getsockname() self.logger.info("Serving HTTP on {0} port {1}...".format(*sa)) if options['browser']: - server_url = "http://{0}:{1}/".format(*sa) + if ipv6: + server_url = "http://[{0}]:{1}/".format(*sa) + else: + server_url = "http://{0}:{1}/".format(*sa) self.logger.info("Opening {0} in the default web browser...".format(server_url)) webbrowser.open(server_url) try: httpd.serve_forever() except KeyboardInterrupt: self.logger.info("Server is shutting down.") - exit(130) + return 130 class OurHTTPRequestHandler(SimpleHTTPRequestHandler): diff --git a/nikola/plugins/command/status.plugin b/nikola/plugins/command/status.plugin new file mode 100644 index 0000000..e02da8b --- /dev/null +++ b/nikola/plugins/command/status.plugin @@ -0,0 +1,9 @@ +[Core] +Name = status +Module = status + +[Documentation] +Author = Daniel Aleksandersen +Version = 1.0 +Website = https://getnikola.com +Description = Site status diff --git a/nikola/plugins/command/status.py b/nikola/plugins/command/status.py new file mode 100644 index 0000000..b8a6a60 --- /dev/null +++ b/nikola/plugins/command/status.py @@ -0,0 +1,140 @@ +# -*- coding: utf-8 -*- + +# Copyright © 2012-2015 Roberto Alsina and others. + +# 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. + +from __future__ import print_function +import io +import os +from datetime import datetime +from dateutil.tz import gettz, tzlocal + +from nikola.plugin_categories import Command + + +class CommandDeploy(Command): + """ Site status. """ + name = "status" + + doc_purpose = "display site status" + doc_description = "Show information about the posts and site deployment." + doc_usage = '[-l|--list-drafts] [-m|--list-modified] [-s|--list-scheduled]' + logger = None + cmd_options = [ + { + 'name': 'list_drafts', + 'short': 'd', + 'long': 'list-drafts', + 'type': bool, + 'default': False, + 'help': 'List all drafts', + }, + { + 'name': 'list_modified', + 'short': 'm', + 'long': 'list-modified', + 'type': bool, + 'default': False, + 'help': 'List all modified files since last deployment', + }, + { + 'name': 'list_scheduled', + 'short': 's', + 'long': 'list-scheduled', + 'type': bool, + 'default': False, + 'help': 'List all scheduled posts', + }, + ] + + def _execute(self, options, args): + + self.site.scan_posts() + + timestamp_path = os.path.join(self.site.config["CACHE_FOLDER"], "lastdeploy") + + last_deploy = None + + try: + with io.open(timestamp_path, "r", encoding="utf8") as inf: + last_deploy = datetime.strptime(inf.read().strip(), "%Y-%m-%dT%H:%M:%S.%f") + last_deploy_offset = datetime.utcnow() - last_deploy + except (IOError, Exception): + print("It does not seem like you’ve ever deployed the site (or cache missing).") + + if last_deploy: + + fmod_since_deployment = [] + for root, dirs, files in os.walk(self.site.config["OUTPUT_FOLDER"], followlinks=True): + if not dirs and not files: + continue + for fname in files: + fpath = os.path.join(root, fname) + fmodtime = datetime.fromtimestamp(os.stat(fpath).st_mtime) + if fmodtime.replace(tzinfo=tzlocal()) > last_deploy.replace(tzinfo=gettz("UTC")).astimezone(tz=tzlocal()): + fmod_since_deployment.append(fpath) + + if len(fmod_since_deployment) > 0: + print("{0} output files modified since last deployment {1} ago.".format(str(len(fmod_since_deployment)), self.human_time(last_deploy_offset))) + if options['list_modified']: + for fpath in fmod_since_deployment: + print("Modified: '{0}'".format(fpath)) + else: + print("Last deployment {0} ago.".format(self.human_time(last_deploy_offset))) + + now = datetime.utcnow().replace(tzinfo=gettz("UTC")) + + posts_count = len(self.site.all_posts) + + # find all drafts + posts_drafts = [post for post in self.site.all_posts if post.is_draft] + posts_drafts = sorted(posts_drafts, key=lambda post: post.source_path) + + # find all scheduled posts with offset from now until publishing time + posts_scheduled = [(post.date - now, post) for post in self.site.all_posts if post.publish_later] + posts_scheduled = sorted(posts_scheduled, key=lambda offset_post: (offset_post[0], offset_post[1].source_path)) + + if len(posts_scheduled) > 0: + if options['list_scheduled']: + for offset, post in posts_scheduled: + print("Scheduled: '{1}' ({2}; source: {3}) in {0}".format(self.human_time(offset), post.meta('title'), post.permalink(), post.source_path)) + else: + offset, post = posts_scheduled[0] + print("{0} to next scheduled post ('{1}'; {2}; source: {3}).".format(self.human_time(offset), post.meta('title'), post.permalink(), post.source_path)) + if options['list_drafts']: + for post in posts_drafts: + print("Draft: '{0}' ({1}; source: {2})".format(post.meta('title'), post.permalink(), post.source_path)) + print("{0} posts in total, {1} scheduled, and {2} drafts.".format(posts_count, len(posts_scheduled), len(posts_drafts))) + + def human_time(self, dt): + days = dt.days + hours = dt.seconds / 60 // 60 + minutes = dt.seconds / 60 - (hours * 60) + if days > 0: + return "{0:.0f} days and {1:.0f} hours".format(days, hours) + elif hours > 0: + return "{0:.0f} hours and {1:.0f} minutes".format(hours, minutes) + elif minutes: + return "{0:.0f} minutes".format(minutes) + return False diff --git a/nikola/plugins/command/version.plugin b/nikola/plugins/command/version.plugin index 3c1ae95..a3f58e8 100644 --- a/nikola/plugins/command/version.plugin +++ b/nikola/plugins/command/version.plugin @@ -4,6 +4,6 @@ Module = version [Documentation] Author = Roberto Alsina -Version = 0.2 +Version = 1.0 Website = http://getnikola.com Description = Show nikola version diff --git a/nikola/plugins/command/version.py b/nikola/plugins/command/version.py index 9b42423..b6520d7 100644 --- a/nikola/plugins/command/version.py +++ b/nikola/plugins/command/version.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -26,19 +26,42 @@ from __future__ import print_function +import lxml +import requests + from nikola.plugin_categories import Command from nikola import __version__ +URL = 'https://pypi.python.org/pypi?:action=doap&name=Nikola' + class CommandVersion(Command): """Print the version.""" name = "version" - doc_usage = "" + doc_usage = "[--check]" needs_config = False doc_purpose = "print the Nikola version number" + cmd_options = [ + { + 'name': 'check', + 'long': 'check', + 'short': '', + 'default': False, + 'type': bool, + 'help': "Check for new versions.", + } + ] def _execute(self, options={}, args=None): """Print the version number.""" print("Nikola v" + __version__) + if options.get('check'): + data = requests.get(URL).text + doc = lxml.etree.fromstring(data.encode('utf8')) + revision = doc.findall('*//{http://usefulinc.com/ns/doap#}revision')[0].text + if revision == __version__: + print("Nikola is up-to-date") + else: + print("The latest version of Nikola is v{0} -- please upgrade using `pip install --upgrade Nikola=={0}` or your system package manager".format(revision)) diff --git a/nikola/plugins/compile/__init__.py b/nikola/plugins/compile/__init__.py index 6ad8bac..a1d17a6 100644 --- a/nikola/plugins/compile/__init__.py +++ b/nikola/plugins/compile/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/compile/html.plugin b/nikola/plugins/compile/html.plugin index 21dd338..66623b2 100644 --- a/nikola/plugins/compile/html.plugin +++ b/nikola/plugins/compile/html.plugin @@ -4,7 +4,7 @@ Module = html [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Compile HTML into HTML (just copy) diff --git a/nikola/plugins/compile/html.py b/nikola/plugins/compile/html.py index 24bf385..ab0c2f6 100644 --- a/nikola/plugins/compile/html.py +++ b/nikola/plugins/compile/html.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -29,18 +29,16 @@ from __future__ import unicode_literals import os -import re import io from nikola.plugin_categories import PageCompiler from nikola.utils import makedirs, write_metadata -_META_SEPARATOR = '(' + os.linesep * 2 + '|' + ('\n' * 2) + '|' + ("\r\n" * 2) + ')' - class CompileHtml(PageCompiler): """Compile HTML into HTML.""" name = "html" + friendly_name = "HTML" def compile_html(self, source, dest, is_two_file=True): makedirs(os.path.dirname(dest)) @@ -48,7 +46,7 @@ class CompileHtml(PageCompiler): with io.open(source, "r", encoding="utf8") as in_file: data = in_file.read() if not is_two_file: - data = re.split(_META_SEPARATOR, data, maxsplit=1)[-1] + _, data = self.split_metadata(data) out_file.write(data) return True diff --git a/nikola/plugins/compile/ipynb.plugin b/nikola/plugins/compile/ipynb.plugin index e258d8a..efe6702 100644 --- a/nikola/plugins/compile/ipynb.plugin +++ b/nikola/plugins/compile/ipynb.plugin @@ -3,8 +3,8 @@ Name = ipynb Module = ipynb [Documentation] -Author = Damian Avila -Version = 1.0 -Website = http://www.oquanta.info -Description = Compile IPython notebooks into HTML +Author = Damian Avila, Chris Warrick and others +Version = 2.0.0 +Website = http://www.damian.oquanta.info/ +Description = Compile IPython notebooks into Nikola posts diff --git a/nikola/plugins/compile/ipynb.py b/nikola/plugins/compile/ipynb.py new file mode 100644 index 0000000..82b76c8 --- /dev/null +++ b/nikola/plugins/compile/ipynb.py @@ -0,0 +1,150 @@ +# -*- coding: utf-8 -*- + +# Copyright © 2013-2015 Damián Avila, Chris Warrick and others. + +# 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. + +"""Implementation of compile_html based on nbconvert.""" + +from __future__ import unicode_literals, print_function +import io +import os +import sys + +try: + import IPython + from IPython.nbconvert.exporters import HTMLExporter + if IPython.version_info[0] >= 3: # API changed with 3.0.0 + from IPython import nbformat + current_nbformat = nbformat.current_nbformat + from IPython.kernel import kernelspec + else: + import IPython.nbformat.current as nbformat + current_nbformat = 'json' + kernelspec = None + + from IPython.config import Config + flag = True +except ImportError: + flag = None + +from nikola.plugin_categories import PageCompiler +from nikola.utils import makedirs, req_missing, get_logger + + +class CompileIPynb(PageCompiler): + """Compile IPynb into HTML.""" + + name = "ipynb" + friendly_name = "Jupyter/IPython Notebook" + demote_headers = True + default_kernel = 'python2' if sys.version_info[0] == 2 else 'python3' + + def set_site(self, site): + self.logger = get_logger('compile_ipynb', site.loghandlers) + super(CompileIPynb, self).set_site(site) + + def compile_html(self, source, dest, is_two_file=True): + if flag is None: + req_missing(['ipython[notebook]>=2.0.0'], 'build this site (compile ipynb)') + makedirs(os.path.dirname(dest)) + HTMLExporter.default_template = 'basic' + c = Config(self.site.config['IPYNB_CONFIG']) + exportHtml = HTMLExporter(config=c) + with io.open(dest, "w+", encoding="utf8") as out_file: + with io.open(source, "r", encoding="utf8") as in_file: + nb_json = nbformat.read(in_file, current_nbformat) + (body, resources) = exportHtml.from_notebook_node(nb_json) + out_file.write(body) + + def read_metadata(self, post, file_metadata_regexp=None, unslugify_titles=False, lang=None): + """read metadata directly from ipynb file. + + As ipynb file support arbitrary metadata as json, the metadata used by Nikola + will be assume to be in the 'nikola' subfield. + """ + if flag is None: + req_missing(['ipython[notebook]>=2.0.0'], 'build this site (compile ipynb)') + source = post.source_path + with io.open(source, "r", encoding="utf8") as in_file: + nb_json = nbformat.read(in_file, current_nbformat) + # Metadata might not exist in two-file posts or in hand-crafted + # .ipynb files. + return nb_json.get('metadata', {}).get('nikola', {}) + + def create_post(self, path, **kw): + if flag is None: + req_missing(['ipython[notebook]>=2.0.0'], 'build this site (compile ipynb)') + content = kw.pop('content', None) + onefile = kw.pop('onefile', False) + kernel = kw.pop('ipython_kernel', None) + # is_page is not needed to create the file + kw.pop('is_page', False) + + metadata = {} + metadata.update(self.default_metadata) + metadata.update(kw) + + makedirs(os.path.dirname(path)) + + if content.startswith("{"): + # imported .ipynb file, guaranteed to start with "{" because it’s JSON. + nb = nbformat.reads(content, current_nbformat) + else: + if IPython.version_info[0] >= 3: + nb = nbformat.v4.new_notebook() + nb["cells"] = [nbformat.v4.new_markdown_cell(content)] + else: + nb = nbformat.new_notebook() + nb["worksheets"] = [nbformat.new_worksheet(cells=[nbformat.new_text_cell('markdown', [content])])] + + if kernelspec is not None: + if kernel is None: + kernel = self.default_kernel + self.logger.notice('No kernel specified, assuming "{0}".'.format(kernel)) + + IPYNB_KERNELS = {} + ksm = kernelspec.KernelSpecManager() + for k in ksm.find_kernel_specs(): + IPYNB_KERNELS[k] = ksm.get_kernel_spec(k).to_dict() + IPYNB_KERNELS[k]['name'] = k + del IPYNB_KERNELS[k]['argv'] + + if kernel not in IPYNB_KERNELS: + self.logger.error('Unknown kernel "{0}". Maybe you mispelled it?'.format(kernel)) + self.logger.info("Available kernels: {0}".format(", ".join(sorted(IPYNB_KERNELS)))) + raise Exception('Unknown kernel "{0}"'.format(kernel)) + + nb["metadata"]["kernelspec"] = IPYNB_KERNELS[kernel] + else: + # Older IPython versions don’t need kernelspecs. + pass + + if onefile: + nb["metadata"]["nikola"] = metadata + + with io.open(path, "w+", encoding="utf8") as fd: + if IPython.version_info[0] >= 3: + nbformat.write(nb, fd, 4) + else: + nbformat.write(nb, fd, 'ipynb') diff --git a/nikola/plugins/compile/ipynb/README.txt b/nikola/plugins/compile/ipynb/README.txt deleted file mode 100644 index 0a7d6db..0000000 --- a/nikola/plugins/compile/ipynb/README.txt +++ /dev/null @@ -1,44 +0,0 @@ -To make this work... - -1- You can install the "jinja-site-ipython" theme using this command: - -$ nikola install_theme -n jinja-site-ipython - -(or xkcd-site-ipython, if you want xkcd styling) - -More info here about themes: -http://getnikola.com/handbook.html#getting-more-themes - -OR - -You can to download the "jinja-site-ipython" theme from here: -https://github.com/damianavila/jinja-site-ipython-theme-for-Nikola -and copy the "site-ipython" folder inside the "themes" folder of your site. - - -2- Then, just add: - -post_pages = ( - ("posts/*.ipynb", "posts", "post.tmpl", True), - ("stories/*.ipynb", "stories", "story.tmpl", False), -) - -and - -THEME = 'jinja-site-ipython' (or 'xkcd-site-ipython', if you want xkcd styling) - -to your conf.py. -Finally... to use it: - -$nikola new_page -f ipynb - -**NOTE**: Just IGNORE the "-1" and "-2" options in nikola new_page command, by default this compiler -create one metadata file and the corresponding naive IPython notebook. - -$nikola build - -And deploy the output folder... to see it locally: $nikola serve -If you have any doubts, just ask: @damianavila - -Cheers. -Damián diff --git a/nikola/plugins/compile/ipynb/__init__.py b/nikola/plugins/compile/ipynb/__init__.py deleted file mode 100644 index 7dde279..0000000 --- a/nikola/plugins/compile/ipynb/__init__.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright © 2013-2014 Damián Avila and others. - -# 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. - -"""Implementation of compile_html based on nbconvert.""" - -from __future__ import unicode_literals, print_function -import io -import os - -try: - from IPython.nbconvert.exporters import HTMLExporter - from IPython.nbformat import current as nbformat - from IPython.config import Config - flag = True -except ImportError: - flag = None - -from nikola.plugin_categories import PageCompiler -from nikola.utils import makedirs, req_missing - - -class CompileIPynb(PageCompiler): - """Compile IPynb into HTML.""" - - name = "ipynb" - supports_onefile = False - demote_headers = True - - def compile_html(self, source, dest, is_two_file=True): - if flag is None: - req_missing(['ipython>=1.1.0'], 'build this site (compile ipynb)') - makedirs(os.path.dirname(dest)) - HTMLExporter.default_template = 'basic' - c = Config(self.site.config['IPYNB_CONFIG']) - exportHtml = HTMLExporter(config=c) - with io.open(dest, "w+", encoding="utf8") as out_file: - with io.open(source, "r", encoding="utf8") as in_file: - nb = in_file.read() - nb_json = nbformat.reads_json(nb) - (body, resources) = exportHtml.from_notebook_node(nb_json) - out_file.write(body) - - def create_post(self, path, **kw): - # content and onefile are ignored by ipynb. - kw.pop('content', None) - onefile = kw.pop('onefile', False) - kw.pop('is_page', False) - - makedirs(os.path.dirname(path)) - if onefile: - raise Exception('The one-file format is not supported by this compiler.') - with io.open(path, "w+", encoding="utf8") as fd: - fd.write("""{ - "metadata": { - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ - { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [], - "language": "python", - "metadata": {}, - "outputs": [] - } - ], - "metadata": {} - } - ] -}""") diff --git a/nikola/plugins/compile/markdown.plugin b/nikola/plugins/compile/markdown.plugin index 157579a..a44b798 100644 --- a/nikola/plugins/compile/markdown.plugin +++ b/nikola/plugins/compile/markdown.plugin @@ -4,7 +4,7 @@ Module = markdown [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Compile Markdown into HTML diff --git a/nikola/plugins/compile/markdown/__init__.py b/nikola/plugins/compile/markdown/__init__.py index 47c7c9b..fbe049d 100644 --- a/nikola/plugins/compile/markdown/__init__.py +++ b/nikola/plugins/compile/markdown/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -30,7 +30,6 @@ from __future__ import unicode_literals import io import os -import re try: from markdown import markdown @@ -45,24 +44,27 @@ from nikola.utils import makedirs, req_missing, write_metadata class CompileMarkdown(PageCompiler): - """Compile markdown into HTML.""" + """Compile Markdown into HTML.""" name = "markdown" + friendly_name = "Markdown" demote_headers = True extensions = [] site = None def set_site(self, site): + self.config_dependencies = [] for plugin_info in site.plugin_manager.getPluginsOfCategory("MarkdownExtension"): if plugin_info.name in site.config['DISABLED_PLUGINS']: site.plugin_manager.removePluginFromCategory(plugin_info, "MarkdownExtension") continue - + self.config_dependencies.append(plugin_info.name) site.plugin_manager.activatePluginByName(plugin_info.name) plugin_info.plugin_object.set_site(site) self.extensions.append(plugin_info.plugin_object) plugin_info.plugin_object.short_help = plugin_info.description + self.config_dependencies.append(str(sorted(site.config.get("MARKDOWN_EXTENSIONS")))) return super(CompileMarkdown, self).set_site(site) def compile_html(self, source, dest, is_two_file=True): @@ -74,7 +76,7 @@ class CompileMarkdown(PageCompiler): with io.open(source, "r", encoding="utf8") as in_file: data = in_file.read() if not is_two_file: - data = re.split('(\n\n|\r\n\r\n)', data, maxsplit=1)[-1] + _, data = self.split_metadata(data) output = markdown(data, self.extensions) out_file.write(output) diff --git a/nikola/plugins/compile/markdown/mdx_gist.py b/nikola/plugins/compile/markdown/mdx_gist.py index 4209bdd..70e7394 100644 --- a/nikola/plugins/compile/markdown/mdx_gist.py +++ b/nikola/plugins/compile/markdown/mdx_gist.py @@ -203,14 +203,11 @@ except ImportError: Extension = Pattern = object from nikola.plugin_categories import MarkdownExtension -from nikola.utils import get_logger, req_missing, STDERR_HANDLER +from nikola.utils import get_logger, STDERR_HANDLER -LOGGER = get_logger('compile_markdown.mdx_gist', STDERR_HANDLER) +import requests -try: - import requests -except ImportError: - requests = None # NOQA +LOGGER = get_logger('compile_markdown.mdx_gist', STDERR_HANDLER) GIST_JS_URL = "https://gist.github.com/{0}.js" GIST_FILE_JS_URL = "https://gist.github.com/{0}.js?file={1}" @@ -261,32 +258,27 @@ class GistPattern(Pattern): gist_elem.set('class', 'gist') script_elem = etree.SubElement(gist_elem, 'script') - if requests: - noscript_elem = etree.SubElement(gist_elem, 'noscript') - - try: - if gist_file: - script_elem.set('src', GIST_FILE_JS_URL.format( - gist_id, gist_file)) - raw_gist = (self.get_raw_gist_with_filename( - gist_id, gist_file)) + noscript_elem = etree.SubElement(gist_elem, 'noscript') - else: - script_elem.set('src', GIST_JS_URL.format( - gist_id)) - raw_gist = (self.get_raw_gist(gist_id)) + try: + if gist_file: + script_elem.set('src', GIST_FILE_JS_URL.format( + gist_id, gist_file)) + raw_gist = (self.get_raw_gist_with_filename( + gist_id, gist_file)) - # Insert source as <pre/> within <noscript> - pre_elem = etree.SubElement(noscript_elem, 'pre') - pre_elem.text = AtomicString(raw_gist) + else: + script_elem.set('src', GIST_JS_URL.format(gist_id)) + raw_gist = (self.get_raw_gist(gist_id)) - except GistFetchException as e: - LOGGER.warn(e.message) - warning_comment = etree.Comment(' WARNING: {0} '.format(e.message)) - noscript_elem.append(warning_comment) + # Insert source as <pre/> within <noscript> + pre_elem = etree.SubElement(noscript_elem, 'pre') + pre_elem.text = AtomicString(raw_gist) - else: - req_missing('requests', 'have inline gist source', optional=True) + except GistFetchException as e: + LOGGER.warn(e.message) + warning_comment = etree.Comment(' WARNING: {0} '.format(e.message)) + noscript_elem.append(warning_comment) return gist_elem diff --git a/nikola/plugins/compile/markdown/mdx_nikola.py b/nikola/plugins/compile/markdown/mdx_nikola.py index ca67511..a03547f 100644 --- a/nikola/plugins/compile/markdown/mdx_nikola.py +++ b/nikola/plugins/compile/markdown/mdx_nikola.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -37,7 +37,6 @@ except ImportError: from nikola.plugin_categories import MarkdownExtension -# FIXME: duplicated with listings.py CODERE = re.compile('<div class="codehilite"><pre>(.*?)</pre></div>', flags=re.MULTILINE | re.DOTALL) @@ -47,6 +46,7 @@ class NikolaPostProcessor(Postprocessor): # python-markdown's highlighter uses <div class="codehilite"><pre> # for code. We switch it to reST's <pre class="code">. + # TODO: monkey-patch for CodeHilite that uses nikola.utils.NikolaPygmentsHTML output = CODERE.sub('<pre class="code literal-block">\\1</pre>', output) return output diff --git a/nikola/plugins/compile/markdown/mdx_podcast.py b/nikola/plugins/compile/markdown/mdx_podcast.py index 9a67910..670973a 100644 --- a/nikola/plugins/compile/markdown/mdx_podcast.py +++ b/nikola/plugins/compile/markdown/mdx_podcast.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# Copyright © 2013-2014 Michael Rabbitt, Roberto Alsina and others. +# Copyright © 2013-2015 Michael Rabbitt, Roberto Alsina and others. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the diff --git a/nikola/plugins/compile/pandoc.plugin b/nikola/plugins/compile/pandoc.plugin index 157b694..ad54b3b 100644 --- a/nikola/plugins/compile/pandoc.plugin +++ b/nikola/plugins/compile/pandoc.plugin @@ -4,7 +4,7 @@ Module = pandoc [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Compile markups into HTML using pandoc diff --git a/nikola/plugins/compile/pandoc.py b/nikola/plugins/compile/pandoc.py index ada8035..361f158 100644 --- a/nikola/plugins/compile/pandoc.py +++ b/nikola/plugins/compile/pandoc.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -30,6 +30,8 @@ You will need, of course, to install pandoc """ +from __future__ import unicode_literals + import io import os import subprocess @@ -42,11 +44,16 @@ class CompilePandoc(PageCompiler): """Compile markups into HTML using pandoc.""" name = "pandoc" + friendly_name = "pandoc" + + def set_site(self, site): + self.config_dependencies = [str(site.config['PANDOC_OPTIONS'])] + super(CompilePandoc, self).set_site(site) def compile_html(self, source, dest, is_two_file=True): makedirs(os.path.dirname(dest)) try: - subprocess.check_call(('pandoc', '-o', dest, source)) + subprocess.check_call(['pandoc', '-o', dest, source] + self.site.config['PANDOC_OPTIONS']) except OSError as e: if e.strreror == 'No such file or directory': req_missing(['pandoc'], 'build this site (compile with pandoc)', python=False) diff --git a/nikola/plugins/compile/php.plugin b/nikola/plugins/compile/php.plugin index ac25259..d6623b5 100644 --- a/nikola/plugins/compile/php.plugin +++ b/nikola/plugins/compile/php.plugin @@ -4,7 +4,7 @@ Module = php [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Compile PHP into HTML (just copy and name the file .php) diff --git a/nikola/plugins/compile/php.py b/nikola/plugins/compile/php.py index 77344fb..bb436e5 100644 --- a/nikola/plugins/compile/php.py +++ b/nikola/plugins/compile/php.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -40,6 +40,7 @@ class CompilePhp(PageCompiler): """Compile PHP into PHP.""" name = "php" + friendly_name = "PHP" def compile_html(self, source, dest, is_two_file=True): makedirs(os.path.dirname(dest)) diff --git a/nikola/plugins/compile/rest.plugin b/nikola/plugins/compile/rest.plugin index 55e9c59..f144809 100644 --- a/nikola/plugins/compile/rest.plugin +++ b/nikola/plugins/compile/rest.plugin @@ -4,7 +4,7 @@ Module = rest [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Compile reSt into HTML diff --git a/nikola/plugins/compile/rest/__init__.py b/nikola/plugins/compile/rest/__init__.py index 98c7151..d446fe8 100644 --- a/nikola/plugins/compile/rest/__init__.py +++ b/nikola/plugins/compile/rest/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -27,66 +27,78 @@ from __future__ import unicode_literals import io import os -import re - -try: - import docutils.core - import docutils.nodes - import docutils.utils - import docutils.io - import docutils.readers.standalone - import docutils.writers.html4css1 - has_docutils = True -except ImportError: - has_docutils = False + +import docutils.core +import docutils.nodes +import docutils.utils +import docutils.io +import docutils.readers.standalone +import docutils.writers.html4css1 from nikola.plugin_categories import PageCompiler -from nikola.utils import get_logger, makedirs, req_missing, write_metadata +from nikola.utils import unicode_str, get_logger, makedirs, write_metadata class CompileRest(PageCompiler): - """Compile reSt into HTML.""" + """Compile reStructuredText into HTML.""" name = "rest" + friendly_name = "reStructuredText" demote_headers = True logger = None - def compile_html(self, source, dest, is_two_file=True): - """Compile reSt into HTML.""" + def _read_extra_deps(self, post): + """Reads contents of .dep file and returns them as a list""" + dep_path = post.base_path + '.dep' + if os.path.isfile(dep_path): + with io.open(dep_path, 'r+', encoding='utf8') as depf: + deps = [l.strip() for l in depf.readlines()] + return deps + return [] + + def register_extra_dependencies(self, post): + """Adds dependency to post object to check .dep file.""" + post.add_dependency(lambda: self._read_extra_deps(post), 'fragment') + + def compile_html_string(self, data, source_path=None, is_two_file=True): + """Compile reSt into HTML strings.""" + # If errors occur, this will be added to the line number reported by + # docutils so the line number matches the actual line number (off by + # 7 with default metadata, could be more or less depending on the post). + add_ln = 0 + if not is_two_file: + m_data, data = self.split_metadata(data) + add_ln = len(m_data.splitlines()) + 1 + + default_template_path = os.path.join(os.path.dirname(__file__), 'template.txt') + output, error_level, deps = rst2html( + data, settings_overrides={ + 'initial_header_level': 1, + 'record_dependencies': True, + 'stylesheet_path': None, + 'link_stylesheet': True, + 'syntax_highlight': 'short', + 'math_output': 'mathjax', + 'template': default_template_path, + }, logger=self.logger, source_path=source_path, l_add_ln=add_ln, transforms=self.site.rst_transforms) + if not isinstance(output, unicode_str): + # To prevent some weird bugs here or there. + # Original issue: empty files. `output` became a bytestring. + output = output.decode('utf-8') + return output, error_level, deps - if not has_docutils: - req_missing(['docutils'], 'build this site (compile reStructuredText)') + def compile_html(self, source, dest, is_two_file=True): + """Compile reSt into HTML files.""" makedirs(os.path.dirname(dest)) error_level = 100 with io.open(dest, "w+", encoding="utf8") as out_file: with io.open(source, "r", encoding="utf8") as in_file: data = in_file.read() - add_ln = 0 - if not is_two_file: - spl = re.split('(\n\n|\r\n\r\n)', data, maxsplit=1) - data = spl[-1] - if len(spl) != 1: - # If errors occur, this will be added to the line - # number reported by docutils so the line number - # matches the actual line number (off by 7 with default - # metadata, could be more or less depending on the post - # author). - add_ln = len(spl[0].splitlines()) + 1 - - default_template_path = os.path.join(os.path.dirname(__file__), 'template.txt') - output, error_level, deps = rst2html( - data, settings_overrides={ - 'initial_header_level': 1, - 'record_dependencies': True, - 'stylesheet_path': None, - 'link_stylesheet': True, - 'syntax_highlight': 'short', - 'math_output': 'mathjax', - 'template': default_template_path, - }, logger=self.logger, source_path=source, l_add_ln=add_ln) + output, error_level, deps = self.compile_html_string(data, source, is_two_file) out_file.write(output) deps_path = dest + '.dep' if deps.list: + deps.list = [p for p in deps.list if p != dest] # Don't depend on yourself (#1671) with io.open(deps_path, "w+", encoding="utf8") as deps_file: deps_file.write('\n'.join(deps.list)) else: @@ -111,15 +123,18 @@ class CompileRest(PageCompiler): with io.open(path, "w+", encoding="utf8") as fd: if onefile: fd.write(write_metadata(metadata)) - fd.write('\n' + content) + fd.write('\n') + fd.write(content) def set_site(self, site): + self.config_dependencies = [] for plugin_info in site.plugin_manager.getPluginsOfCategory("RestExtension"): if plugin_info.name in site.config['DISABLED_PLUGINS']: site.plugin_manager.removePluginFromCategory(plugin_info, "RestExtension") continue site.plugin_manager.activatePluginByName(plugin_info.name) + self.config_dependencies.append(plugin_info.name) plugin_info.plugin_object.set_site(site) plugin_info.plugin_object.short_help = plugin_info.description @@ -160,6 +175,13 @@ def get_observer(settings): class NikolaReader(docutils.readers.standalone.Reader): + def __init__(self, *args, **kwargs): + self.transforms = kwargs.pop('transforms', []) + docutils.readers.standalone.Reader.__init__(self, *args, **kwargs) + + def get_transforms(self): + return docutils.readers.standalone.Reader(self).get_transforms() + self.transforms + def new_document(self): """Create and return a new empty document tree (root node).""" document = docutils.utils.new_document(self.source.source_path, self.settings) @@ -199,7 +221,7 @@ def add_node(node, visit_function=None, depart_function=None): def depart_Math(self, node): self.body.append('</math>') - For full example, you can refer to `Microdata plugin <http://plugins.getnikola.com/#microdata>`_ + For full example, you can refer to `Microdata plugin <https://plugins.getnikola.com/#microdata>`_ """ docutils.nodes._add_node_class_names([node.__name__]) if visit_function: @@ -213,7 +235,7 @@ def rst2html(source, source_path=None, source_class=docutils.io.StringInput, parser=None, parser_name='restructuredtext', writer=None, writer_name='html', settings=None, settings_spec=None, settings_overrides=None, config_section=None, - enable_exit_status=None, logger=None, l_add_ln=0): + enable_exit_status=None, logger=None, l_add_ln=0, transforms=None): """ Set up & run a `Publisher`, and return a dictionary of document parts. Dictionary keys are the names of parts, and values are Unicode strings; @@ -231,7 +253,7 @@ def rst2html(source, source_path=None, source_class=docutils.io.StringInput, reStructuredText syntax errors. """ if reader is None: - reader = NikolaReader() + reader = NikolaReader(transforms=transforms) # For our custom logging, we have special needs and special settings we # specify here. # logger a logger from Nikola diff --git a/nikola/plugins/compile/rest/chart.py b/nikola/plugins/compile/rest/chart.py index 55ddf5c..59b9dc7 100644 --- a/nikola/plugins/compile/rest/chart.py +++ b/nikola/plugins/compile/rest/chart.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/compile/rest/doc.py b/nikola/plugins/compile/rest/doc.py index 6143606..703c234 100644 --- a/nikola/plugins/compile/rest/doc.py +++ b/nikola/plugins/compile/rest/doc.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/compile/rest/gist.py b/nikola/plugins/compile/rest/gist.py index 65189b5..ab4d56d 100644 --- a/nikola/plugins/compile/rest/gist.py +++ b/nikola/plugins/compile/rest/gist.py @@ -1,16 +1,11 @@ # -*- coding: utf-8 -*- # This file is public domain according to its author, Brian Hsu +import requests from docutils.parsers.rst import Directive, directives from docutils import nodes -try: - import requests -except ImportError: - requests = None # NOQA - from nikola.plugin_categories import RestExtension -from nikola.utils import req_missing class Plugin(RestExtension): @@ -64,22 +59,15 @@ class GitHubGist(Directive): if 'file' in self.options: filename = self.options['file'] - if requests is not None: - rawGist = (self.get_raw_gist_with_filename(gistID, filename)) + rawGist = (self.get_raw_gist_with_filename(gistID, filename)) embedHTML = ('<script src="https://gist.github.com/{0}.js' '?file={1}"></script>').format(gistID, filename) else: - if requests is not None: - rawGist = (self.get_raw_gist(gistID)) + rawGist = (self.get_raw_gist(gistID)) embedHTML = ('<script src="https://gist.github.com/{0}.js">' '</script>').format(gistID) - if requests is None: - reqnode = nodes.raw( - '', req_missing('requests', 'have inline gist source', - optional=True), format='html') - else: - reqnode = nodes.literal_block('', rawGist) + reqnode = nodes.literal_block('', rawGist) return [nodes.raw('', embedHTML, format='html'), nodes.raw('', '<noscript>', format='html'), diff --git a/nikola/plugins/compile/rest/listing.py b/nikola/plugins/compile/rest/listing.py index 23ec254..b8340cf 100644 --- a/nikola/plugins/compile/rest/listing.py +++ b/nikola/plugins/compile/rest/listing.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -31,43 +31,95 @@ from __future__ import unicode_literals import io import os +import uuid try: from urlparse import urlunsplit except ImportError: from urllib.parse import urlunsplit # NOQA +import docutils.parsers.rst.directives.body +import docutils.parsers.rst.directives.misc from docutils import core from docutils import nodes from docutils.parsers.rst import Directive, directives +from docutils.parsers.rst.roles import set_classes from docutils.parsers.rst.directives.misc import Include -try: - from docutils.parsers.rst.directives.body import CodeBlock -except ImportError: # docutils < 0.9 (Debian Sid For The Loss) - class CodeBlock(Directive): - required_arguments = 1 - has_content = True - option_spec = {} - CODE = '<pre>{0}</pre>' - - def run(self): - """ Required by the Directive interface. Create docutils nodes """ - return [nodes.raw('', self.CODE.format('\n'.join(self.content)), format='html')] - directives.register_directive('code', CodeBlock) +from pygments.lexers import get_lexer_by_name +import pygments +import pygments.util +from nikola import utils from nikola.plugin_categories import RestExtension -# Add sphinx compatibility option -CodeBlock.option_spec['linenos'] = directives.unchanged - -class FlexibleCodeBlock(CodeBlock): +# A sanitized version of docutils.parsers.rst.directives.body.CodeBlock. +class CodeBlock(Directive): + """Parse and mark up content of a code block.""" + optional_arguments = 1 + option_spec = {'class': directives.class_option, + 'name': directives.unchanged, + 'number-lines': directives.unchanged, # integer or None + 'linenos': directives.unchanged, + 'tab-width': directives.nonnegative_int} + has_content = True def run(self): + self.assert_has_content() + if 'linenos' in self.options: self.options['number-lines'] = self.options['linenos'] - return super(FlexibleCodeBlock, self).run() -CodeBlock = FlexibleCodeBlock + if 'tab-width' in self.options: + self.content = [x.replace('\t', ' ' * self.options['tab-width']) for x in self.content] + + if self.arguments: + language = self.arguments[0] + else: + language = 'text' + set_classes(self.options) + classes = ['code'] + if language: + classes.append(language) + if 'classes' in self.options: + classes.extend(self.options['classes']) + + code = '\n'.join(self.content) + + try: + lexer = get_lexer_by_name(language) + except pygments.util.ClassNotFound: + raise self.error('Cannot find pygments lexer for language "{0}"'.format(language)) + + if 'number-lines' in self.options: + linenos = 'table' + # optional argument `startline`, defaults to 1 + try: + linenostart = int(self.options['number-lines'] or 1) + except ValueError: + raise self.error(':number-lines: with non-integer start value') + else: + linenos = False + linenostart = 1 # actually unused + + if self.site.invariant: # for testing purposes + anchor_ref = 'rest_code_' + 'fixedvaluethatisnotauuid' + else: + anchor_ref = 'rest_code_' + uuid.uuid4().hex + + formatter = utils.NikolaPygmentsHTML(anchor_ref=anchor_ref, classes=classes, linenos=linenos, linenostart=linenostart) + out = pygments.highlight(code, lexer, formatter) + node = nodes.raw('', out, format='html') + + self.add_name(node) + # if called from "include", set the source + if 'source' in self.options: + node.attributes['source'] = self.options['source'] + + return [node] + +# Monkey-patch: replace insane docutils CodeBlock with our implementation. +docutils.parsers.rst.directives.body.CodeBlock = CodeBlock +docutils.parsers.rst.directives.misc.CodeBlock = CodeBlock class Plugin(RestExtension): @@ -79,11 +131,15 @@ class Plugin(RestExtension): # Even though listings don't use CodeBlock anymore, I am # leaving these to make the code directive work with # docutils < 0.9 + CodeBlock.site = site + directives.register_directive('code', CodeBlock) directives.register_directive('code-block', CodeBlock) directives.register_directive('sourcecode', CodeBlock) directives.register_directive('listing', Listing) + Listing.folders = site.config['LISTINGS_FOLDERS'] return super(Plugin, self).set_site(site) + # Add sphinx compatibility option listing_spec = Include.option_spec listing_spec['linenos'] = directives.unchanged @@ -104,9 +160,17 @@ class Listing(Include): option_spec = listing_spec def run(self): - fname = self.arguments.pop(0) + _fname = self.arguments.pop(0) + fname = _fname.replace('/', os.sep) lang = self.arguments.pop(0) - fpath = os.path.join('listings', fname) + if len(self.folders) == 1: + listings_folder = next(iter(self.folders.keys())) + if fname.startswith(listings_folder): + fpath = os.path.join(fname) # new syntax: specify folder name + else: + fpath = os.path.join(listings_folder, fname) # old syntax: don't specify folder name + else: + fpath = os.path.join(fname) # must be new syntax: specify folder name self.arguments.insert(0, fpath) self.options['code'] = lang if 'linenos' in self.options: @@ -114,9 +178,9 @@ class Listing(Include): with io.open(fpath, 'r+', encoding='utf8') as fileobject: self.content = fileobject.read().splitlines() self.state.document.settings.record_dependencies.add(fpath) - target = urlunsplit(("link", 'listing', fname, '', '')) + target = urlunsplit(("link", 'listing', fpath.replace('\\', '/'), '', '')) generated_nodes = ( - [core.publish_doctree('`{0} <{1}>`_'.format(fname, target))[0]]) + [core.publish_doctree('`{0} <{1}>`_'.format(_fname, target))[0]]) generated_nodes += self.get_code_from_file(fileobject) return generated_nodes diff --git a/nikola/plugins/compile/rest/media.py b/nikola/plugins/compile/rest/media.py index ccda559..0363d28 100644 --- a/nikola/plugins/compile/rest/media.py +++ b/nikola/plugins/compile/rest/media.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/compile/rest/post_list.py b/nikola/plugins/compile/rest/post_list.py index f719e31..ddbd82d 100644 --- a/nikola/plugins/compile/rest/post_list.py +++ b/nikola/plugins/compile/rest/post_list.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2013-2014 Udo Spallek, Roberto Alsina and others. +# Copyright © 2013-2015 Udo Spallek, Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -25,7 +25,9 @@ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import unicode_literals +import os import uuid +import natsort from docutils import nodes from docutils.parsers.rst import Directive, directives @@ -52,7 +54,7 @@ class PostList(Directive): Post List ========= :Directive Arguments: None. - :Directive Options: lang, start, stop, reverse, tags, template, id + :Directive Options: lang, start, stop, reverse, sort, tags, template, id :Directive Content: None. Provides a reStructuredText directive to create a list of posts. @@ -77,6 +79,10 @@ class PostList(Directive): Reverse the order of the post-list. Defaults is to not reverse the order of posts. + ``sort``: string + Sort post list by one of each post's attributes, usually ``title`` or a + custom ``priority``. Defaults to None (chronological sorting). + ``tags`` : string [, string...] Filter posts to show only posts having at least one of the ``tags``. Defaults to None. @@ -105,6 +111,7 @@ class PostList(Directive): 'start': int, 'stop': int, 'reverse': directives.flag, + 'sort': directives.unchanged, 'tags': directives.unchanged, 'slugs': directives.unchanged, 'all': directives.flag, @@ -124,6 +131,7 @@ class PostList(Directive): show_all = self.options.get('all', False) lang = self.options.get('lang', utils.LocaleBorg().current_lang) template = self.options.get('template', 'post_list_directive.tmpl') + sort = self.options.get('sort') if self.site.invariant: # for testing purposes post_list_id = self.options.get('id', 'post_list_' + 'fixedvaluethatisnotauuid') else: @@ -150,6 +158,9 @@ class PostList(Directive): filtered_timeline.append(post) + if sort: + filtered_timeline = natsort.natsorted(filtered_timeline, key=lambda post: post.meta[lang][sort], alg=natsort.ns.F | natsort.ns.IC) + for post in filtered_timeline[start:stop:step]: if slugs: cont = True @@ -160,10 +171,15 @@ class PostList(Directive): if cont: continue + bp = post.translated_base_path(lang) + if os.path.exists(bp): + self.state.document.settings.record_dependencies.add(bp) + posts += [post] if not posts: return [] + self.state.document.settings.record_dependencies.add("####MAGIC####TIMELINE") template_data = { 'lang': lang, diff --git a/nikola/plugins/compile/rest/slides.py b/nikola/plugins/compile/rest/slides.py index ea8e413..7826f6a 100644 --- a/nikola/plugins/compile/rest/slides.py +++ b/nikola/plugins/compile/rest/slides.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/compile/rest/thumbnail.plugin b/nikola/plugins/compile/rest/thumbnail.plugin new file mode 100644 index 0000000..3b73340 --- /dev/null +++ b/nikola/plugins/compile/rest/thumbnail.plugin @@ -0,0 +1,9 @@ +[Core] +Name = rest_thumbnail +Module = thumbnail + +[Documentation] +Author = Pelle Nilsson +Version = 0.1 +Website = http://getnikola.com +Description = reST directive to facilitate enlargeable images with thumbnails diff --git a/nikola/plugins/compile/rest/thumbnail.py b/nikola/plugins/compile/rest/thumbnail.py new file mode 100644 index 0000000..5388d8d --- /dev/null +++ b/nikola/plugins/compile/rest/thumbnail.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- + +# Copyright © 2014-2015 Pelle Nilsson and others. + +# 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. + +import os + +from docutils.parsers.rst import directives +from docutils.parsers.rst.directives.images import Image, Figure + +from nikola.plugin_categories import RestExtension + + +class Plugin(RestExtension): + + name = "rest_thumbnail" + + def set_site(self, site): + self.site = site + directives.register_directive('thumbnail', Thumbnail) + return super(Plugin, self).set_site(site) + + +class Thumbnail(Figure): + + def align(argument): + return directives.choice(argument, Image.align_values) + + def figwidth_value(argument): + if argument.lower() == 'image': + return 'image' + else: + return directives.length_or_percentage_or_unitless(argument, 'px') + + option_spec = Image.option_spec.copy() + option_spec['figwidth'] = figwidth_value + option_spec['figclass'] = directives.class_option + has_content = True + + def run(self): + uri = directives.uri(self.arguments[0]) + self.options['target'] = uri + self.arguments[0] = '.thumbnail'.join(os.path.splitext(uri)) + if self.content: + (node,) = Figure.run(self) + else: + (node,) = Image.run(self) + return [node] diff --git a/nikola/plugins/compile/rest/vimeo.py b/nikola/plugins/compile/rest/vimeo.py index 4b34dfe..bc44b0e 100644 --- a/nikola/plugins/compile/rest/vimeo.py +++ b/nikola/plugins/compile/rest/vimeo.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -28,15 +28,11 @@ from docutils import nodes from docutils.parsers.rst import Directive, directives -try: - import requests -except ImportError: - requests = None # NOQA +import requests import json from nikola.plugin_categories import RestExtension -from nikola.utils import req_missing class Plugin(RestExtension): @@ -94,10 +90,6 @@ class Vimeo(Directive): return [nodes.raw('', CODE.format(**options), format='html')] def check_modules(self): - msg = None - if requests is None: - msg = req_missing(['requests'], 'use the vimeo directive', optional=True) - return [nodes.raw('', '<div class="text-error">{0}</div>'.format(msg), format='html')] return None def set_video_size(self): diff --git a/nikola/plugins/compile/rest/youtube.py b/nikola/plugins/compile/rest/youtube.py index b32e77a..7c6bba1 100644 --- a/nikola/plugins/compile/rest/youtube.py +++ b/nikola/plugins/compile/rest/youtube.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/loghandler/__init__.py b/nikola/plugins/loghandler/__init__.py index 6ad8bac..a1d17a6 100644 --- a/nikola/plugins/loghandler/__init__.py +++ b/nikola/plugins/loghandler/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/loghandler/smtp.plugin b/nikola/plugins/loghandler/smtp.plugin index e914b3d..38c1d96 100644 --- a/nikola/plugins/loghandler/smtp.plugin +++ b/nikola/plugins/loghandler/smtp.plugin @@ -4,6 +4,6 @@ Module = smtp [Documentation] Author = Daniel Devine -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Log over smtp (email). diff --git a/nikola/plugins/loghandler/smtp.py b/nikola/plugins/loghandler/smtp.py index 2c9fd9c..146a658 100644 --- a/nikola/plugins/loghandler/smtp.py +++ b/nikola/plugins/loghandler/smtp.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Daniel Devine and others. +# Copyright © 2012-2015 Daniel Devine and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/loghandler/stderr.plugin b/nikola/plugins/loghandler/stderr.plugin index 211d2b4..6c20ea1 100644 --- a/nikola/plugins/loghandler/stderr.plugin +++ b/nikola/plugins/loghandler/stderr.plugin @@ -4,6 +4,6 @@ Module = stderr [Documentation] Author = Daniel Devine -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Log to stderr, the default logger. diff --git a/nikola/plugins/loghandler/stderr.py b/nikola/plugins/loghandler/stderr.py index 593c381..79ace68 100644 --- a/nikola/plugins/loghandler/stderr.py +++ b/nikola/plugins/loghandler/stderr.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Daniel Devine and others. +# Copyright © 2012-2015 Daniel Devine and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/misc/scan_posts.plugin b/nikola/plugins/misc/scan_posts.plugin new file mode 100644 index 0000000..6d2351f --- /dev/null +++ b/nikola/plugins/misc/scan_posts.plugin @@ -0,0 +1,10 @@ +[Core] +Name = scan_posts +Module = scan_posts + +[Documentation] +Author = Roberto Alsina +Version = 1.0 +Website = http://getnikola.com +Description = Scan posts and create timeline + diff --git a/nikola/plugins/misc/scan_posts.py b/nikola/plugins/misc/scan_posts.py new file mode 100644 index 0000000..a6f04e6 --- /dev/null +++ b/nikola/plugins/misc/scan_posts.py @@ -0,0 +1,100 @@ +# -*- coding: utf-8 -*- + +# Copyright © 2012-2015 Roberto Alsina and others. + +# 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. + +from __future__ import unicode_literals, print_function +import glob +import os +import sys + +from nikola.plugin_categories import PostScanner +from nikola import utils +from nikola.post import Post + + +class ScanPosts(PostScanner): + """Render pages into output.""" + + name = "scan_posts" + + def scan(self): + """Create list of posts from POSTS and PAGES options.""" + + seen = set([]) + if not self.site.quiet: + print("Scanning posts", end='', file=sys.stderr) + + timeline = [] + + for wildcard, destination, template_name, use_in_feeds in \ + self.site.config['post_pages']: + if not self.site.quiet: + print(".", end='', file=sys.stderr) + dirname = os.path.dirname(wildcard) + for dirpath, _, _ in os.walk(dirname, followlinks=True): + dest_dir = os.path.normpath(os.path.join(destination, + os.path.relpath(dirpath, dirname))) # output/destination/foo/ + # Get all the untranslated paths + dir_glob = os.path.join(dirpath, os.path.basename(wildcard)) # posts/foo/*.rst + untranslated = glob.glob(dir_glob) + # And now get all the translated paths + translated = set([]) + for lang in self.site.config['TRANSLATIONS'].keys(): + if lang == self.site.config['DEFAULT_LANG']: + continue + lang_glob = utils.get_translation_candidate(self.site.config, dir_glob, lang) # posts/foo/*.LANG.rst + translated = translated.union(set(glob.glob(lang_glob))) + # untranslated globs like *.rst often match translated paths too, so remove them + # and ensure x.rst is not in the translated set + untranslated = set(untranslated) - translated + + # also remove from translated paths that are translations of + # paths in untranslated_list, so x.es.rst is not in the untranslated set + for p in untranslated: + translated = translated - set([utils.get_translation_candidate(self.site.config, p, l) for l in self.site.config['TRANSLATIONS'].keys()]) + + full_list = list(translated) + list(untranslated) + # We eliminate from the list the files inside any .ipynb folder + full_list = [p for p in full_list + if not any([x.startswith('.') + for x in p.split(os.sep)])] + + for base_path in full_list: + if base_path in seen: + continue + else: + seen.add(base_path) + post = Post( + base_path, + self.site.config, + dest_dir, + use_in_feeds, + self.site.MESSAGES, + template_name, + self.site.get_compiler(base_path) + ) + timeline.append(post) + + return timeline diff --git a/nikola/plugins/task/__init__.py b/nikola/plugins/task/__init__.py index 6ad8bac..a1d17a6 100644 --- a/nikola/plugins/task/__init__.py +++ b/nikola/plugins/task/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/task/archive.plugin b/nikola/plugins/task/archive.plugin index 448b115..6687209 100644 --- a/nikola/plugins/task/archive.plugin +++ b/nikola/plugins/task/archive.plugin @@ -4,7 +4,7 @@ Module = archive [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Generates the blog's archive pages. diff --git a/nikola/plugins/task/archive.py b/nikola/plugins/task/archive.py index 4f1ab19..533be69 100644 --- a/nikola/plugins/task/archive.py +++ b/nikola/plugins/task/archive.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -24,12 +24,14 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +import copy import os # for tearDown with _reload we cannot use 'import from' to access LocaleBorg import nikola.utils +import datetime from nikola.plugin_categories import Task -from nikola.utils import config_changed +from nikola.utils import config_changed, adjust_name_for_index_path, adjust_name_for_index_link class Archive(Task): @@ -39,133 +41,191 @@ class Archive(Task): def set_site(self, site): site.register_path_handler('archive', self.archive_path) + site.register_path_handler('archive_atom', self.archive_atom_path) return super(Archive, self).set_site(site) + def _prepare_task(self, kw, name, lang, posts, items, template_name, + title, deps_translatable=None): + # name: used to build permalink and destination + # posts, items: posts or items; only one of them should be used, + # the other be None + # template_name: name of the template to use + # title: the (translated) title for the generated page + # deps_translatable: dependencies (None if not added) + assert posts is not None or items is not None + + context = {} + context["lang"] = lang + context["title"] = title + context["permalink"] = self.site.link("archive", name, lang) + if posts is not None: + context["posts"] = posts + n = len(posts) + else: + context["items"] = items + n = len(items) + task = self.site.generic_post_list_renderer( + lang, + [], + os.path.join(kw['output_folder'], self.site.path("archive", name, lang)), + template_name, + kw['filters'], + context, + ) + + task_cfg = {1: copy.copy(kw), 2: n} + if deps_translatable is not None: + task_cfg[3] = deps_translatable + task['uptodate'] = task['uptodate'] + [config_changed(task_cfg, 'nikola.plugins.task.archive')] + task['basename'] = self.name + return task + + def _generate_posts_task(self, kw, name, lang, posts, title, deps_translatable=None): + posts = sorted(posts, key=lambda a: a.date) + posts.reverse() + if kw['archives_are_indexes']: + def page_link(i, displayed_i, num_pages, force_addition, extension=None): + feed = "_atom" if extension == ".atom" else "" + return adjust_name_for_index_link(self.site.link("archive" + feed, name, lang), i, displayed_i, + lang, self.site, force_addition, extension) + + def page_path(i, displayed_i, num_pages, force_addition, extension=None): + feed = "_atom" if extension == ".atom" else "" + return adjust_name_for_index_path(self.site.path("archive" + feed, name, lang), i, displayed_i, + lang, self.site, force_addition, extension) + + uptodate = [] + if deps_translatable is not None: + uptodate += [config_changed(deps_translatable, 'nikola.plugins.task.archive')] + yield self.site.generic_index_renderer( + lang, + posts, + title, + "archiveindex.tmpl", + {"archive_name": name, + "is_feed_stale": kw["is_feed_stale"]}, + kw, + str(self.name), + page_link, + page_path, + uptodate) + else: + yield self._prepare_task(kw, name, lang, posts, None, "list_post.tmpl", title, deps_translatable) + def gen_tasks(self): kw = { "messages": self.site.MESSAGES, "translations": self.site.config['TRANSLATIONS'], "output_folder": self.site.config['OUTPUT_FOLDER'], "filters": self.site.config['FILTERS'], + "archives_are_indexes": self.site.config['ARCHIVES_ARE_INDEXES'], "create_monthly_archive": self.site.config['CREATE_MONTHLY_ARCHIVE'], "create_single_archive": self.site.config['CREATE_SINGLE_ARCHIVE'], + "show_untranslated_posts": self.site.config['SHOW_UNTRANSLATED_POSTS'], + "create_full_archives": self.site.config['CREATE_FULL_ARCHIVES'], + "create_daily_archive": self.site.config['CREATE_DAILY_ARCHIVE'], + "pretty_urls": self.site.config['PRETTY_URLS'], + "strip_indexes": self.site.config['STRIP_INDEXES'], + "index_file": self.site.config['INDEX_FILE'], + "generate_atom": self.site.config["GENERATE_ATOM"], } self.site.scan_posts() yield self.group_task() # TODO add next/prev links for years - if kw['create_monthly_archive'] and kw['create_single_archive']: + if (kw['create_monthly_archive'] and kw['create_single_archive']) and not kw['create_full_archives']: raise Exception('Cannot create monthly and single archives at the same time.') for lang in kw["translations"]: - archdata = self.site.posts_per_year - # A bit of a hack. - if kw['create_single_archive']: - archdata = {None: self.site.posts} + if kw['create_single_archive'] and not kw['create_full_archives']: + # if we are creating one single archive + archdata = {} + else: + # if we are not creating one single archive, start with all years + archdata = self.site.posts_per_year.copy() + if kw['create_single_archive'] or kw['create_full_archives']: + # if we are creating one single archive, or full archives + archdata[None] = self.site.posts # for create_single_archive for year, posts in archdata.items(): - output_name = os.path.join( - kw['output_folder'], self.site.path("archive", year, lang)) - context = {} - context["lang"] = lang + # Filter untranslated posts (Issue #1360) + if not kw["show_untranslated_posts"]: + posts = [p for p in posts if lang in p.translated_to] + + # Add archive per year or total archive if year: - context["title"] = kw["messages"][lang]["Posts for year %s"] % year + title = kw["messages"][lang]["Posts for year %s"] % year + kw["is_feed_stale"] = (datetime.datetime.utcnow().strftime("%Y") != year) else: - context["title"] = kw["messages"][lang]["Archive"] - context["permalink"] = self.site.link("archive", year, lang) - if not kw["create_monthly_archive"]: - template_name = "list_post.tmpl" - post_list = sorted(posts, key=lambda a: a.date) - post_list.reverse() - context["posts"] = post_list - else: # Monthly archives, just list the months - months = set([(m.split('/')[1], self.site.link("archive", m, lang)) for m in self.site.posts_per_month.keys() if m.startswith(str(year))]) - months = sorted(list(months)) - months.reverse() - template_name = "list.tmpl" - context["items"] = [[nikola.utils.LocaleBorg().get_month_name(int(month), lang), link] for month, link in months] - post_list = [] - task = self.site.generic_post_list_renderer( - lang, - [], - output_name, - template_name, - kw['filters'], - context, - ) - n = len(post_list) if 'posts' in context else len(months) - + title = kw["messages"][lang]["Archive"] + kw["is_feed_stale"] = False deps_translatable = {} for k in self.site._GLOBAL_CONTEXT_TRANSLATABLE: deps_translatable[k] = self.site.GLOBAL_CONTEXT[k](lang) + if not kw["create_monthly_archive"] or kw["create_full_archives"]: + yield self._generate_posts_task(kw, year, lang, posts, title, deps_translatable) + else: + months = set([(m.split('/')[1], self.site.link("archive", m, lang)) for m in self.site.posts_per_month.keys() if m.startswith(str(year))]) + months = sorted(list(months)) + months.reverse() + items = [[nikola.utils.LocaleBorg().get_month_name(int(month), lang), link] for month, link in months] + yield self._prepare_task(kw, year, lang, None, items, "list.tmpl", title, deps_translatable) - task_cfg = {1: task['uptodate'][0].config, 2: kw, 3: n, 4: deps_translatable} - task['uptodate'] = [config_changed(task_cfg)] - task['basename'] = self.name - yield task - - if not kw["create_monthly_archive"]: + if not kw["create_monthly_archive"] and not kw["create_full_archives"] and not kw["create_daily_archive"]: continue # Just to avoid nesting the other loop in this if - template_name = "list_post.tmpl" for yearmonth, posts in self.site.posts_per_month.items(): - output_name = os.path.join( - kw['output_folder'], self.site.path("archive", yearmonth, - lang)) + # Add archive per month year, month = yearmonth.split('/') - post_list = sorted(posts, key=lambda a: a.date) - post_list.reverse() - context = {} - context["lang"] = lang - context["posts"] = post_list - context["permalink"] = self.site.link("archive", year, lang) - - context["title"] = kw["messages"][lang]["Posts for {month} {year}"].format( - year=year, month=nikola.utils.LocaleBorg().get_month_name(int(month), lang)) - task = self.site.generic_post_list_renderer( - lang, - post_list, - output_name, - template_name, - kw['filters'], - context, - ) - task_cfg = {1: task['uptodate'][0].config, 2: kw, 3: len(post_list)} - task['uptodate'] = [config_changed(task_cfg)] - task['basename'] = self.name - yield task - - if not kw['create_single_archive']: + + kw["is_feed_stale"] = (datetime.datetime.utcnow().strftime("%Y/%m") != yearmonth) + + # Filter untranslated posts (via Issue #1360) + if not kw["show_untranslated_posts"]: + posts = [p for p in posts if lang in p.translated_to] + + if kw["create_monthly_archive"] or kw["create_full_archives"]: + title = kw["messages"][lang]["Posts for {month} {year}"].format( + year=year, month=nikola.utils.LocaleBorg().get_month_name(int(month), lang)) + yield self._generate_posts_task(kw, yearmonth, lang, posts, title) + + if not kw["create_full_archives"] and not kw["create_daily_archive"]: + continue # Just to avoid nesting the other loop in this if + # Add archive per day + days = dict() + for p in posts: + if p.date.day not in days: + days[p.date.day] = list() + days[p.date.day].append(p) + for day, posts in days.items(): + title = kw["messages"][lang]["Posts for {month} {day}, {year}"].format( + year=year, month=nikola.utils.LocaleBorg().get_month_name(int(month), lang), day=day) + yield self._generate_posts_task(kw, yearmonth + '/{0:02d}'.format(day), lang, posts, title) + + if not kw['create_single_archive'] and not kw['create_full_archives']: # And an "all your years" page for yearly and monthly archives + if "is_feed_stale" in kw: + del kw["is_feed_stale"] years = list(self.site.posts_per_year.keys()) years.sort(reverse=True) - template_name = "list.tmpl" kw['years'] = years for lang in kw["translations"]: - context = {} - output_name = os.path.join( - kw['output_folder'], self.site.path("archive", None, - lang)) - context["title"] = kw["messages"][lang]["Archive"] - context["items"] = [(y, self.site.link("archive", y, lang)) - for y in years] - context["permalink"] = self.site.link("archive", None, lang) - task = self.site.generic_post_list_renderer( - lang, - [], - output_name, - template_name, - kw['filters'], - context, - ) - task_cfg = {1: task['uptodate'][0].config, 2: kw, 3: len(years)} - task['uptodate'] = [config_changed(task_cfg)] - task['basename'] = self.name - yield task - - def archive_path(self, name, lang): + items = [(y, self.site.link("archive", y, lang)) for y in years] + yield self._prepare_task(kw, None, lang, None, items, "list.tmpl", kw["messages"][lang]["Archive"]) + + def archive_path(self, name, lang, is_feed=False): + if is_feed: + extension = ".atom" + archive_file = os.path.splitext(self.site.config['ARCHIVE_FILENAME'])[0] + extension + index_file = os.path.splitext(self.site.config['INDEX_FILE'])[0] + extension + else: + archive_file = self.site.config['ARCHIVE_FILENAME'] + index_file = self.site.config['INDEX_FILE'] if name: return [_f for _f in [self.site.config['TRANSLATIONS'][lang], self.site.config['ARCHIVE_PATH'], name, - self.site.config['INDEX_FILE']] if _f] + index_file] if _f] else: return [_f for _f in [self.site.config['TRANSLATIONS'][lang], self.site.config['ARCHIVE_PATH'], - self.site.config['ARCHIVE_FILENAME']] if _f] + archive_file] if _f] + + def archive_atom_path(self, name, lang): + return self.archive_path(name, lang, is_feed=True) diff --git a/nikola/plugins/task/bundles.plugin b/nikola/plugins/task/bundles.plugin index e0b0a4d..3fe049b 100644 --- a/nikola/plugins/task/bundles.plugin +++ b/nikola/plugins/task/bundles.plugin @@ -4,7 +4,7 @@ Module = bundles [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Theme bundles using WebAssets diff --git a/nikola/plugins/task/bundles.py b/nikola/plugins/task/bundles.py index fca6924..6f88d0c 100644 --- a/nikola/plugins/task/bundles.py +++ b/nikola/plugins/task/bundles.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -43,11 +43,12 @@ class BuildBundles(LateTask): name = "create_bundles" def set_site(self, site): - super(BuildBundles, self).set_site(site) - if webassets is None and self.site.config['USE_BUNDLES']: + self.logger = utils.get_logger('bundles', site.loghandlers) + if webassets is None and site.config['USE_BUNDLES']: utils.req_missing(['webassets'], 'USE_BUNDLES', optional=True) - utils.LOGGER.warn('Setting USE_BUNDLES to False.') - self.site.config['USE_BUNDLES'] = False + self.logger.warn('Setting USE_BUNDLES to False.') + site.config['USE_BUNDLES'] = False + super(BuildBundles, self).set_site(site) def gen_tasks(self): """Bundle assets using WebAssets.""" @@ -74,7 +75,12 @@ class BuildBundles(LateTask): bundle = webassets.Bundle(*inputs, output=os.path.basename(output)) env.register(output, bundle) # This generates the file - env[output].urls() + try: + env[output].urls() + except Exception as e: + self.logger.error("Failed to build bundles.") + self.logger.exception(e) + self.logger.notice("Try running ``nikola clean`` and building again.") else: with open(os.path.join(out_dir, os.path.basename(output)), 'wb+'): pass # Create empty file @@ -91,8 +97,7 @@ class BuildBundles(LateTask): files.append(os.path.join(dname, fname)) file_dep = [os.path.join(kw['output_folder'], fname) for fname in files if - utils.get_asset_path(fname, self.site.THEMES, self.site.config['FILES_FOLDERS']) - or fname == 'assets/css/code.css'] + utils.get_asset_path(fname, self.site.THEMES, self.site.config['FILES_FOLDERS']) or fname == os.path.join('assets', 'css', 'code.css')] # code.css will be generated by us if it does not exist in # FILES_FOLDERS or theme assets. It is guaranteed that the # generation will happen before this task. @@ -107,7 +112,7 @@ class BuildBundles(LateTask): utils.config_changed({ 1: kw, 2: file_dep - })], + }, 'nikola.plugins.task.bundles')], 'clean': True, } yield utils.apply_filters(task, kw['filters']) diff --git a/nikola/plugins/task/copy_assets.plugin b/nikola/plugins/task/copy_assets.plugin index 28b9e32..0530ebf 100644 --- a/nikola/plugins/task/copy_assets.plugin +++ b/nikola/plugins/task/copy_assets.plugin @@ -4,7 +4,7 @@ Module = copy_assets [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Copy theme assets into output. diff --git a/nikola/plugins/task/copy_assets.py b/nikola/plugins/task/copy_assets.py index 29aa083..a72bfdf 100644 --- a/nikola/plugins/task/copy_assets.py +++ b/nikola/plugins/task/copy_assets.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -72,7 +72,7 @@ class CopyAssets(Task): if task['name'] in tasks: continue tasks[task['name']] = task - task['uptodate'] = [utils.config_changed(kw)] + task['uptodate'] = [utils.config_changed(kw, 'nikola.plugins.task.copy_assets')] task['basename'] = self.name if code_css_input: task['file_dep'] = [code_css_input] @@ -99,7 +99,7 @@ class CopyAssets(Task): 'basename': self.name, 'name': code_css_path, 'targets': [code_css_path], - 'uptodate': [utils.config_changed(kw), testcontents], + 'uptodate': [utils.config_changed(kw, 'nikola.plugins.task.copy_assets'), testcontents], 'actions': [(create_code_css, [])], 'clean': True, } diff --git a/nikola/plugins/task/copy_files.plugin b/nikola/plugins/task/copy_files.plugin index 45c9e0d..073676b 100644 --- a/nikola/plugins/task/copy_files.plugin +++ b/nikola/plugins/task/copy_files.plugin @@ -4,7 +4,7 @@ Module = copy_files [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Copy static files into the output. diff --git a/nikola/plugins/task/copy_files.py b/nikola/plugins/task/copy_files.py index 1d31756..9a039f1 100644 --- a/nikola/plugins/task/copy_files.py +++ b/nikola/plugins/task/copy_files.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -51,5 +51,5 @@ class CopyFiles(Task): real_dst = os.path.join(dst, kw['files_folders'][src]) for task in utils.copy_tree(src, real_dst, link_cutoff=dst): task['basename'] = self.name - task['uptodate'] = [utils.config_changed(kw)] + task['uptodate'] = [utils.config_changed(kw, 'nikola.plugins.task.copy_files')] yield utils.apply_filters(task, filters, skip_ext=['.html']) diff --git a/nikola/plugins/task/galleries.plugin b/nikola/plugins/task/galleries.plugin index 8352151..73085cd 100644 --- a/nikola/plugins/task/galleries.plugin +++ b/nikola/plugins/task/galleries.plugin @@ -4,7 +4,7 @@ Module = galleries [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Create image galleries automatically. diff --git a/nikola/plugins/task/galleries.py b/nikola/plugins/task/galleries.py index f835444..e887f18 100644 --- a/nikola/plugins/task/galleries.py +++ b/nikola/plugins/task/galleries.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -31,34 +31,30 @@ import glob import json import mimetypes import os +import sys try: from urlparse import urljoin except ImportError: from urllib.parse import urljoin # NOQA import natsort -Image = None try: - from PIL import Image, ExifTags # NOQA + from PIL import Image # NOQA except ImportError: - try: - import Image as _Image - import ExifTags - Image = _Image - except ImportError: - pass + import Image as _Image + Image = _Image import PyRSS2Gen as rss from nikola.plugin_categories import Task from nikola import utils +from nikola.image_processing import ImageProcessor from nikola.post import Post -from nikola.utils import req_missing _image_size_cache = {} -class Galleries(Task): +class Galleries(Task, ImageProcessor): """Render image galleries.""" name = 'render_galleries' @@ -66,47 +62,84 @@ class Galleries(Task): def set_site(self, site): site.register_path_handler('gallery', self.gallery_path) + site.register_path_handler('gallery_global', self.gallery_global_path) site.register_path_handler('gallery_rss', self.gallery_rss_path) + + self.logger = utils.get_logger('render_galleries', site.loghandlers) + + self.kw = { + 'thumbnail_size': site.config['THUMBNAIL_SIZE'], + 'max_image_size': site.config['MAX_IMAGE_SIZE'], + 'output_folder': site.config['OUTPUT_FOLDER'], + 'cache_folder': site.config['CACHE_FOLDER'], + 'default_lang': site.config['DEFAULT_LANG'], + 'use_filename_as_title': site.config['USE_FILENAME_AS_TITLE'], + 'gallery_folders': site.config['GALLERY_FOLDERS'], + 'sort_by_date': site.config['GALLERY_SORT_BY_DATE'], + 'filters': site.config['FILTERS'], + 'translations': site.config['TRANSLATIONS'], + 'global_context': site.GLOBAL_CONTEXT, + 'feed_length': site.config['FEED_LENGTH'], + 'tzinfo': site.tzinfo, + 'comments_in_galleries': site.config['COMMENTS_IN_GALLERIES'], + 'generate_rss': site.config['GENERATE_RSS'], + } + + # Verify that no folder in GALLERY_FOLDERS appears twice + appearing_paths = set() + for source, dest in self.kw['gallery_folders'].items(): + if source in appearing_paths or dest in appearing_paths: + problem = source if source in appearing_paths else dest + utils.LOGGER.error("The gallery input or output folder '{0}' appears in more than one entry in GALLERY_FOLDERS, exiting.".format(problem)) + sys.exit(1) + appearing_paths.add(source) + appearing_paths.add(dest) + + # Find all galleries we need to process + self.find_galleries() + # Create self.gallery_links + self.create_galleries_paths() + return super(Galleries, self).set_site(site) + def _find_gallery_path(self, name): + # The system using self.proper_gallery_links and self.improper_gallery_links + # is similar as in listings.py. + if name in self.proper_gallery_links: + return self.proper_gallery_links[name] + elif name in self.improper_gallery_links: + candidates = self.improper_gallery_links[name] + if len(candidates) == 1: + return candidates[0] + self.logger.error("Gallery name '{0}' is not unique! Possible output paths: {1}".format(name, candidates)) + else: + self.logger.error("Unknown gallery '{0}'!".format(name)) + self.logger.info("Known galleries: " + str(list(self.proper_gallery_links.keys()))) + sys.exit(1) + def gallery_path(self, name, lang): - return [_f for _f in [self.site.config['TRANSLATIONS'][lang], - self.site.config['GALLERY_PATH'], name, - self.site.config['INDEX_FILE']] if _f] + gallery_path = self._find_gallery_path(name) + return [_f for _f in [self.site.config['TRANSLATIONS'][lang]] + + gallery_path.split(os.sep) + + [self.site.config['INDEX_FILE']] if _f] + + def gallery_global_path(self, name, lang): + gallery_path = self._find_gallery_path(name) + return [_f for _f in gallery_path.split(os.sep) + + [self.site.config['INDEX_FILE']] if _f] def gallery_rss_path(self, name, lang): - return [_f for _f in [self.site.config['TRANSLATIONS'][lang], - self.site.config['GALLERY_PATH'], name, - 'rss.xml'] if _f] + gallery_path = self._find_gallery_path(name) + return [_f for _f in [self.site.config['TRANSLATIONS'][lang]] + + gallery_path.split(os.sep) + + ['rss.xml'] if _f] def gen_tasks(self): """Render image galleries.""" - if Image is None: - req_missing(['pillow'], 'render galleries') - - self.logger = utils.get_logger('render_galleries', self.site.loghandlers) - self.image_ext_list = ['.jpg', '.png', '.jpeg', '.gif', '.svg', '.bmp', '.tiff'] + self.image_ext_list = self.image_ext_list_builtin self.image_ext_list.extend(self.site.config.get('EXTRA_IMAGE_EXTENSIONS', [])) - self.kw = { - 'thumbnail_size': self.site.config['THUMBNAIL_SIZE'], - 'max_image_size': self.site.config['MAX_IMAGE_SIZE'], - 'output_folder': self.site.config['OUTPUT_FOLDER'], - 'cache_folder': self.site.config['CACHE_FOLDER'], - 'default_lang': self.site.config['DEFAULT_LANG'], - 'use_filename_as_title': self.site.config['USE_FILENAME_AS_TITLE'], - 'gallery_path': self.site.config['GALLERY_PATH'], - 'sort_by_date': self.site.config['GALLERY_SORT_BY_DATE'], - 'filters': self.site.config['FILTERS'], - 'translations': self.site.config['TRANSLATIONS'], - 'global_context': self.site.GLOBAL_CONTEXT, - 'feed_length': self.site.config['FEED_LENGTH'], - 'tzinfo': self.site.tzinfo, - 'comments_in_galleries': self.site.config['COMMENTS_IN_GALLERIES'], - 'generate_rss': self.site.config['GENERATE_RSS'], - } - for k, v in self.site.GLOBAL_CONTEXT['template_hooks'].items(): self.kw['||template_hooks|{0}||'.format(k)] = v._items @@ -114,22 +147,19 @@ class Galleries(Task): template_name = "gallery.tmpl" - # Find all galleries we need to process - self.find_galleries() - # Create all output folders for task in self.create_galleries(): yield task # For each gallery: - for gallery in self.gallery_list: + for gallery, input_folder, output_folder in self.gallery_list: # Create subfolder list folder_list = [(x, x.split(os.sep)[-2]) for x in glob.glob(os.path.join(gallery, '*') + os.sep)] # Parse index into a post (with translations) - post = self.parse_index(gallery) + post = self.parse_index(gallery, input_folder, output_folder) # Create image list, filter exclusions image_list = self.get_image_list(gallery) @@ -143,12 +173,12 @@ class Galleries(Task): # Create thumbnails and large images in destination for image in image_list: - for task in self.create_target_images(image): + for task in self.create_target_images(image, input_folder): yield task # Remove excluded images for image in self.get_excluded_images(gallery): - for task in self.remove_excluded_image(image): + for task in self.remove_excluded_image(image, input_folder): yield task crumbs = utils.get_crumbs(gallery, index_folder=self) @@ -160,9 +190,7 @@ class Galleries(Task): dst = os.path.join( self.kw['output_folder'], - self.site.path( - "gallery", - os.path.relpath(gallery, self.kw['gallery_path']), lang)) + self.site.path("gallery", gallery, lang)) dst = os.path.normpath(dst) for k in self.site._GLOBAL_CONTEXT_TRANSLATABLE: @@ -187,25 +215,27 @@ class Galleries(Task): img_titles = [''] * len(image_name_list) thumbs = ['.thumbnail'.join(os.path.splitext(p)) for p in image_list] - thumbs = [os.path.join(self.kw['output_folder'], t) for t in thumbs] - dest_img_list = [os.path.join(self.kw['output_folder'], t) for t in image_list] + thumbs = [os.path.join(self.kw['output_folder'], output_folder, os.path.relpath(t, input_folder)) for t in thumbs] + dst_img_list = [os.path.join(output_folder, os.path.relpath(t, input_folder)) for t in image_list] + dest_img_list = [os.path.join(self.kw['output_folder'], t) for t in dst_img_list] folders = [] # Generate friendly gallery names for path, folder in folder_list: - fpost = self.parse_index(path) + fpost = self.parse_index(path, input_folder, output_folder) if fpost: ft = fpost.title(lang) or folder else: ft = folder + if not folder.endswith('/'): + folder += '/' folders.append((folder, ft)) - context["folders"] = natsort.natsorted(folders) + context["folders"] = natsort.natsorted( + folders, alg=natsort.ns.F | natsort.ns.IC) context["crumbs"] = crumbs - context["permalink"] = self.site.link( - "gallery", os.path.basename( - os.path.relpath(gallery, self.kw['gallery_path'])), lang) + context["permalink"] = self.site.link("gallery", gallery, lang) context["enable_comments"] = self.kw['comments_in_galleries'] context["thumbnail_size"] = self.kw["thumbnail_size"] @@ -216,15 +246,18 @@ class Galleries(Task): 'targets': [post.translated_base_path(lang)], 'file_dep': post.fragment_deps(lang), 'actions': [(post.compile, [lang])], - 'uptodate': [utils.config_changed(self.kw)] + 'uptodate': [utils.config_changed(self.kw, 'nikola.plugins.task.galleries:post')] + post.fragment_deps_uptodate(lang) } context['post'] = post else: context['post'] = None file_dep = self.site.template_system.template_deps( template_name) + image_list + thumbs + file_dep_dest = self.site.template_system.template_deps( + template_name) + dest_img_list + thumbs if post: file_dep += [post.translated_base_path(l) for l in self.kw['translations']] + file_dep_dest += [post.translated_base_path(l) for l in self.kw['translations']] yield utils.apply_filters({ 'basename': self.name, @@ -244,58 +277,87 @@ class Galleries(Task): 'uptodate': [utils.config_changed({ 1: self.kw, 2: self.site.config["COMMENTS_IN_GALLERIES"], - 3: context, - })], + 3: context.copy(), + }, 'nikola.plugins.task.galleries:gallery')], }, self.kw['filters']) # RSS for the gallery if self.kw["generate_rss"]: rss_dst = os.path.join( self.kw['output_folder'], - self.site.path( - "gallery_rss", - os.path.relpath(gallery, self.kw['gallery_path']), lang)) + self.site.path("gallery_rss", gallery, lang)) rss_dst = os.path.normpath(rss_dst) yield utils.apply_filters({ 'basename': self.name, 'name': rss_dst, - 'file_dep': file_dep, + 'file_dep': file_dep_dest, 'targets': [rss_dst], 'actions': [ (self.gallery_rss, ( image_list, + dst_img_list, img_titles, lang, - self.site.link( - "gallery_rss", os.path.basename(gallery), lang), + self.site.link("gallery_rss", gallery, lang), rss_dst, context['title'] ))], 'clean': True, 'uptodate': [utils.config_changed({ 1: self.kw, - })], + }, 'nikola.plugins.task.galleries:rss')], }, self.kw['filters']) def find_galleries(self): """Find all galleries to be processed according to conf.py""" self.gallery_list = [] - for root, dirs, files in os.walk(self.kw['gallery_path'], followlinks=True): - self.gallery_list.append(root) + for input_folder, output_folder in self.kw['gallery_folders'].items(): + for root, dirs, files in os.walk(input_folder, followlinks=True): + self.gallery_list.append((root, input_folder, output_folder)) + + def create_galleries_paths(self): + """Given a list of galleries, puts their paths into self.gallery_links.""" + + # gallery_path is "gallery/foo/name" + self.proper_gallery_links = dict() + self.improper_gallery_links = dict() + for gallery_path, input_folder, output_folder in self.gallery_list: + if gallery_path == input_folder: + gallery_name = '' + # special case, because relpath will return '.' in this case + else: + gallery_name = os.path.relpath(gallery_path, input_folder) + + output_path = os.path.join(output_folder, gallery_name) + self.proper_gallery_links[gallery_path] = output_path + self.proper_gallery_links[output_path] = output_path + + # If the input and output names differ, the gallery is accessible + # only by `input` and `output/`. + output_path_noslash = output_path[:-1] + if output_path_noslash not in self.proper_gallery_links: + self.proper_gallery_links[output_path_noslash] = output_path + + gallery_path_slash = gallery_path + '/' + if gallery_path_slash not in self.proper_gallery_links: + self.proper_gallery_links[gallery_path_slash] = output_path + + if gallery_name not in self.improper_gallery_links: + self.improper_gallery_links[gallery_name] = list() + self.improper_gallery_links[gallery_name].append(output_path) def create_galleries(self): """Given a list of galleries, create the output folders.""" # gallery_path is "gallery/foo/name" - for gallery_path in self.gallery_list: - gallery_name = os.path.relpath(gallery_path, self.kw['gallery_path']) + for gallery_path, input_folder, _ in self.gallery_list: # have to use dirname because site.path returns .../index.html output_gallery = os.path.dirname( os.path.join( self.kw["output_folder"], - self.site.path("gallery", gallery_name))) + self.site.path("gallery", gallery_path))) output_gallery = os.path.normpath(output_gallery) # Task to create gallery in output/ yield { @@ -304,16 +366,16 @@ class Galleries(Task): 'actions': [(utils.makedirs, (output_gallery,))], 'targets': [output_gallery], 'clean': True, - 'uptodate': [utils.config_changed(self.kw)], + 'uptodate': [utils.config_changed(self.kw, 'nikola.plugins.task.galleries:mkdir')], } - def parse_index(self, gallery): + def parse_index(self, gallery, input_folder, output_folder): """Returns a Post object if there is an index.txt.""" index_path = os.path.join(gallery, "index.txt") destination = os.path.join( - self.kw["output_folder"], - gallery) + self.kw["output_folder"], output_folder, + os.path.relpath(gallery, input_folder)) if os.path.isfile(index_path): post = Post( index_path, @@ -361,12 +423,12 @@ class Galleries(Task): image_list = list(image_set) return image_list - def create_target_images(self, img): - gallery_name = os.path.relpath(os.path.dirname(img), self.kw['gallery_path']) + def create_target_images(self, img, input_path): + gallery_name = os.path.dirname(img) output_gallery = os.path.dirname( os.path.join( self.kw["output_folder"], - self.site.path("gallery", gallery_name))) + self.site.path("gallery_global", gallery_name))) # Do thumbnails and copy originals # img is "galleries/name/image_name.jpg" # img_name is "image_name.jpg" @@ -392,7 +454,7 @@ class Galleries(Task): 'clean': True, 'uptodate': [utils.config_changed({ 1: self.kw['thumbnail_size'] - })], + }, 'nikola.plugins.task.galleries:resize_thumb')], }, self.kw['filters']) yield utils.apply_filters({ @@ -407,19 +469,19 @@ class Galleries(Task): 'clean': True, 'uptodate': [utils.config_changed({ 1: self.kw['max_image_size'] - })], + }, 'nikola.plugins.task.galleries:resize_max')], }, self.kw['filters']) - def remove_excluded_image(self, img): + def remove_excluded_image(self, img, input_folder): # Remove excluded images - # img is something like galleries/demo/tesla2_lg.jpg so it's the *source* path + # img is something like input_folder/demo/tesla2_lg.jpg so it's the *source* path # and we should remove both the large and thumbnail *destination* paths - img = os.path.relpath(img, self.kw['gallery_path']) output_folder = os.path.dirname( os.path.join( self.kw["output_folder"], - self.site.path("gallery", os.path.dirname(img)))) + self.site.path("gallery_global", os.path.dirname(img)))) + img = os.path.relpath(img, input_folder) img_path = os.path.join(output_folder, os.path.basename(img)) fname, ext = os.path.splitext(img_path) thumb_path = fname + '.thumbnail' + ext @@ -431,7 +493,7 @@ class Galleries(Task): (utils.remove_file, (thumb_path,)) ], 'clean': True, - 'uptodate': [utils.config_changed(self.kw)], + 'uptodate': [utils.config_changed(self.kw, 'nikola.plugins.task.galleries:clean_thumb')], }, self.kw['filters']) yield utils.apply_filters({ @@ -441,7 +503,7 @@ class Galleries(Task): (utils.remove_file, (img_path,)) ], 'clean': True, - 'uptodate': [utils.config_changed(self.kw)], + 'uptodate': [utils.config_changed(self.kw, 'nikola.plugins.task.galleries:clean_file')], }, self.kw['filters']) def render_gallery_index( @@ -484,7 +546,7 @@ class Galleries(Task): context['photo_array_json'] = json.dumps(photo_array) self.site.render_template(template_name, output_name, context) - def gallery_rss(self, img_list, img_titles, lang, permalink, output_path, title): + def gallery_rss(self, img_list, dest_img_list, img_titles, lang, permalink, output_path, title): """Create a RSS showing the latest images in the gallery. This doesn't use generic_rss_renderer because it @@ -492,10 +554,10 @@ class Galleries(Task): """ def make_url(url): - return urljoin(self.site.config['BASE_URL'], url) + return urljoin(self.site.config['BASE_URL'], url.lstrip('/')) items = [] - for img, title in list(zip(img_list, img_titles))[:self.kw["feed_length"]]: + for img, srcimg, title in list(zip(dest_img_list, img_list, img_titles))[:self.kw["feed_length"]]: img_size = os.stat( os.path.join( self.site.config['OUTPUT_FOLDER'], img)).st_size @@ -503,7 +565,7 @@ class Galleries(Task): 'title': title, 'link': make_url(img), 'guid': rss.Guid(img, False), - 'pubDate': self.image_date(img), + 'pubDate': self.image_date(srcimg), 'enclosure': rss.Enclosure( make_url(img), img_size, @@ -515,12 +577,15 @@ class Galleries(Task): title=title, link=make_url(permalink), description='', - lastBuildDate=datetime.datetime.now(), + lastBuildDate=datetime.datetime.utcnow(), items=items, generator='http://getnikola.com/', language=lang ) + rss_obj.rss_attrs["xmlns:dc"] = "http://purl.org/dc/elements/1.1/" + rss_obj.self_url = make_url(permalink) + rss_obj.rss_attrs["xmlns:atom"] = "http://www.w3.org/2005/Atom" dst_dir = os.path.dirname(output_path) utils.makedirs(dst_dir) with io.open(output_path, "w+", encoding="utf-8") as rss_file: @@ -528,66 +593,3 @@ class Galleries(Task): if isinstance(data, utils.bytes_str): data = data.decode('utf-8') rss_file.write(data) - - def resize_image(self, src, dst, max_size): - """Make a copy of the image in the requested size.""" - if not Image: - utils.copy_file(src, dst) - return - im = Image.open(src) - w, h = im.size - if w > max_size or h > max_size: - size = max_size, max_size - - # Panoramas get larger thumbnails because they look *awful* - if w > 2 * h: - size = min(w, max_size * 4), min(w, max_size * 4) - - try: - exif = im._getexif() - except Exception: - exif = None - if exif is not None: - for tag, value in list(exif.items()): - decoded = ExifTags.TAGS.get(tag, tag) - - if decoded == 'Orientation': - if value == 3: - im = im.rotate(180) - elif value == 6: - im = im.rotate(270) - elif value == 8: - im = im.rotate(90) - break - try: - im.thumbnail(size, Image.ANTIALIAS) - im.save(dst) - except Exception as e: - self.logger.warn("Can't thumbnail {0}, using original " - "image as thumbnail ({1})".format(src, e)) - utils.copy_file(src, dst) - else: # Image is small - utils.copy_file(src, dst) - - def image_date(self, src): - """Try to figure out the date of the image.""" - if src not in self.dates: - try: - im = Image.open(src) - exif = im._getexif() - except Exception: - exif = None - if exif is not None: - for tag, value in list(exif.items()): - decoded = ExifTags.TAGS.get(tag, tag) - if decoded in ('DateTimeOriginal', 'DateTimeDigitized'): - try: - self.dates[src] = datetime.datetime.strptime( - value, r'%Y:%m:%d %H:%M:%S') - break - except ValueError: # Invalid EXIF date. - pass - if src not in self.dates: - self.dates[src] = datetime.datetime.fromtimestamp( - os.stat(src).st_mtime) - return self.dates[src] diff --git a/nikola/plugins/task/gzip.plugin b/nikola/plugins/task/gzip.plugin index b68ea6f..4867fd6 100644 --- a/nikola/plugins/task/gzip.plugin +++ b/nikola/plugins/task/gzip.plugin @@ -4,7 +4,7 @@ Module = gzip [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Create gzipped copies of files diff --git a/nikola/plugins/task/gzip.py b/nikola/plugins/task/gzip.py index bcc9637..5799839 100644 --- a/nikola/plugins/task/gzip.py +++ b/nikola/plugins/task/gzip.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/task/indexes.plugin b/nikola/plugins/task/indexes.plugin index a18942c..5d2bf5a 100644 --- a/nikola/plugins/task/indexes.plugin +++ b/nikola/plugins/task/indexes.plugin @@ -4,7 +4,7 @@ Module = indexes [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Generates the blog's index pages. diff --git a/nikola/plugins/task/indexes.py b/nikola/plugins/task/indexes.py index 0a2cd02..03d36b1 100644 --- a/nikola/plugins/task/indexes.py +++ b/nikola/plugins/task/indexes.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -29,7 +29,7 @@ from collections import defaultdict import os from nikola.plugin_categories import Task -from nikola.utils import config_changed +from nikola import utils class Indexes(Task): @@ -39,6 +39,7 @@ class Indexes(Task): def set_site(self, site): site.register_path_handler('index', self.index_path) + site.register_path_handler('index_atom', self.index_atom_path) return super(Indexes, self).set_site(site) def gen_tasks(self): @@ -47,85 +48,39 @@ class Indexes(Task): kw = { "translations": self.site.config['TRANSLATIONS'], - "index_display_post_count": - self.site.config['INDEX_DISPLAY_POST_COUNT'], "messages": self.site.MESSAGES, - "index_teasers": self.site.config['INDEX_TEASERS'], "output_folder": self.site.config['OUTPUT_FOLDER'], "filters": self.site.config['FILTERS'], "show_untranslated_posts": self.site.config['SHOW_UNTRANSLATED_POSTS'], + "index_display_post_count": self.site.config['INDEX_DISPLAY_POST_COUNT'], "indexes_title": self.site.config['INDEXES_TITLE'], - "indexes_pages": self.site.config['INDEXES_PAGES'], - "indexes_pages_main": self.site.config['INDEXES_PAGES_MAIN'], "blog_title": self.site.config["BLOG_TITLE"], - "rss_read_more_link": self.site.config["RSS_READ_MORE_LINK"], + "generate_atom": self.site.config["GENERATE_ATOM"], } template_name = "index.tmpl" posts = self.site.posts + self.number_of_pages = dict() for lang in kw["translations"]: - # Split in smaller lists - lists = [] + def page_link(i, displayed_i, num_pages, force_addition, extension=None): + feed = "_atom" if extension == ".atom" else "" + return utils.adjust_name_for_index_link(self.site.link("index" + feed, None, lang), i, displayed_i, + lang, self.site, force_addition, extension) + + def page_path(i, displayed_i, num_pages, force_addition, extension=None): + feed = "_atom" if extension == ".atom" else "" + return utils.adjust_name_for_index_path(self.site.path("index" + feed, None, lang), i, displayed_i, + lang, self.site, force_addition, extension) + if kw["show_untranslated_posts"]: filtered_posts = posts else: filtered_posts = [x for x in posts if x.is_translation_available(lang)] - lists.append(filtered_posts[:kw["index_display_post_count"]]) - filtered_posts = filtered_posts[kw["index_display_post_count"]:] - while filtered_posts: - lists.append(filtered_posts[-kw["index_display_post_count"]:]) - filtered_posts = filtered_posts[:-kw["index_display_post_count"]] - num_pages = len(lists) - for i, post_list in enumerate(lists): - context = {} - indexes_title = kw['indexes_title'] or kw['blog_title'](lang) - if kw["indexes_pages_main"]: - ipages_i = i + 1 - ipages_msg = "page %d" - else: - ipages_i = i - ipages_msg = "old posts, page %d" - if kw["indexes_pages"]: - indexes_pages = kw["indexes_pages"] % ipages_i - else: - indexes_pages = " (" + \ - kw["messages"][lang][ipages_msg] % ipages_i + ")" - if i > 0 or kw["indexes_pages_main"]: - context["title"] = indexes_title + indexes_pages - else: - context["title"] = indexes_title - context["prevlink"] = None - context["nextlink"] = None - context['index_teasers'] = kw['index_teasers'] - if i == 0: # index.html page - context["prevlink"] = None - if num_pages > 1: - context["nextlink"] = "index-{0}.html".format(num_pages - 1) - else: - context["nextlink"] = None - else: # index-x.html pages - if i > 1: - context["nextlink"] = "index-{0}.html".format(i - 1) - if i < num_pages - 1: - context["prevlink"] = "index-{0}.html".format(i + 1) - elif i == num_pages - 1: - context["prevlink"] = "index.html" - context["permalink"] = self.site.link("index", i, lang) - output_name = os.path.join( - kw['output_folder'], self.site.path("index", i, - lang)) - task = self.site.generic_post_list_renderer( - lang, - post_list, - output_name, - template_name, - kw['filters'], - context, - ) - task_cfg = {1: task['uptodate'][0].config, 2: kw} - task['uptodate'] = [config_changed(task_cfg)] - task['basename'] = 'render_indexes' - yield task + + indexes_title = kw['indexes_title'](lang) or kw['blog_title'](lang) + self.number_of_pages[lang] = (len(filtered_posts) + kw['index_display_post_count'] - 1) // kw['index_display_post_count'] + + yield self.site.generic_index_renderer(lang, filtered_posts, indexes_title, template_name, {}, kw, 'render_indexes', page_link, page_path) if not self.site.config["STORY_INDEX"]: return @@ -135,6 +90,7 @@ class Indexes(Task): "output_folder": self.site.config['OUTPUT_FOLDER'], "filters": self.site.config['FILTERS'], "index_file": self.site.config['INDEX_FILE'], + "strip_indexes": self.site.config['STRIP_INDEXES'], } template_name = "list.tmpl" for lang in kw["translations"]: @@ -151,6 +107,12 @@ class Indexes(Task): should_render = True output_name = os.path.join(kw['output_folder'], dirname, kw['index_file']) short_destination = os.path.join(dirname, kw['index_file']) + link = short_destination.replace('\\', '/') + index_len = len(kw['index_file']) + if kw['strip_indexes'] and link[-(1 + index_len):] == '/' + kw['index_file']: + link = link[:-index_len] + context["permalink"] = link + for post in post_list: # If there is an index.html pending to be created from # a story, do not generate the STORY_INDEX @@ -166,18 +128,25 @@ class Indexes(Task): template_name, kw['filters'], context) - task_cfg = {1: task['uptodate'][0].config, 2: kw} - task['uptodate'] = [config_changed(task_cfg)] + task['uptodate'] = task['uptodate'] + [utils.config_changed(kw, 'nikola.plugins.task.indexes')] task['basename'] = self.name yield task - def index_path(self, name, lang): - if name not in [None, 0]: - return [_f for _f in [self.site.config['TRANSLATIONS'][lang], - self.site.config['INDEX_PATH'], - 'index-{0}.html'.format(name)] if _f] + def index_path(self, name, lang, is_feed=False): + extension = None + if is_feed: + extension = ".atom" + index_file = os.path.splitext(self.site.config['INDEX_FILE'])[0] + extension else: - return [_f for _f in [self.site.config['TRANSLATIONS'][lang], - self.site.config['INDEX_PATH'], - self.site.config['INDEX_FILE']] - if _f] + index_file = self.site.config['INDEX_FILE'] + return utils.adjust_name_for_index_path_list([_f for _f in [self.site.config['TRANSLATIONS'][lang], + self.site.config['INDEX_PATH'], + index_file] if _f], + name, + utils.get_displayed_page_number(name, self.number_of_pages[lang], self.site), + lang, + self.site, + extension=extension) + + def index_atom_path(self, name, lang): + return self.index_path(name, lang, is_feed=True) diff --git a/nikola/plugins/task/listings.plugin b/nikola/plugins/task/listings.plugin index c93184d..a5ba77a 100644 --- a/nikola/plugins/task/listings.plugin +++ b/nikola/plugins/task/listings.plugin @@ -4,7 +4,7 @@ Module = listings [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Render code listings into output diff --git a/nikola/plugins/task/listings.py b/nikola/plugins/task/listings.py index 79f6763..b913330 100644 --- a/nikola/plugins/task/listings.py +++ b/nikola/plugins/task/listings.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -26,74 +26,115 @@ from __future__ import unicode_literals, print_function +import sys import os from pygments import highlight from pygments.lexers import get_lexer_for_filename, TextLexer -from pygments.formatters import HtmlFormatter import natsort -import re from nikola.plugin_categories import Task from nikola import utils -# FIXME: (almost) duplicated with mdx_nikola.py -CODERE = re.compile('<div class="code"><pre>(.*?)</pre></div>', flags=re.MULTILINE | re.DOTALL) - - class Listings(Task): """Render pretty listings.""" name = "render_listings" + def register_output_name(self, input_folder, rel_name, rel_output_name): + """Register proper and improper file mappings.""" + if rel_name not in self.improper_input_file_mapping: + self.improper_input_file_mapping[rel_name] = [] + self.improper_input_file_mapping[rel_name].append(rel_output_name) + self.proper_input_file_mapping[os.path.join(input_folder, rel_name)] = rel_output_name + self.proper_input_file_mapping[rel_output_name] = rel_output_name + def set_site(self, site): site.register_path_handler('listing', self.listing_path) + + # We need to prepare some things for the listings path handler to work. + + self.kw = { + "default_lang": site.config["DEFAULT_LANG"], + "listings_folders": site.config["LISTINGS_FOLDERS"], + "output_folder": site.config["OUTPUT_FOLDER"], + "index_file": site.config["INDEX_FILE"], + "strip_indexes": site.config['STRIP_INDEXES'], + "filters": site.config["FILTERS"], + } + + # Verify that no folder in LISTINGS_FOLDERS appears twice (on output side) + appearing_paths = set() + for source, dest in self.kw['listings_folders'].items(): + if source in appearing_paths or dest in appearing_paths: + problem = source if source in appearing_paths else dest + utils.LOGGER.error("The listings input or output folder '{0}' appears in more than one entry in LISTINGS_FOLDERS, exiting.".format(problem)) + sys.exit(1) + appearing_paths.add(source) + appearing_paths.add(dest) + + # improper_input_file_mapping maps a relative input file (relative to + # its corresponding input directory) to a list of the output files. + # Since several input directories can contain files of the same name, + # a list is needed. This is needed for compatibility to previous Nikola + # versions, where there was no need to specify the input directory name + # when asking for a link via site.link('listing', ...). + self.improper_input_file_mapping = {} + + # proper_input_file_mapping maps relative input file (relative to CWD) + # to a generated output file. Since we don't allow an input directory + # to appear more than once in LISTINGS_FOLDERS, we can map directly to + # a file name (and not a list of files). + self.proper_input_file_mapping = {} + + for input_folder, output_folder in self.kw['listings_folders'].items(): + for root, dirs, files in os.walk(input_folder, followlinks=True): + # Compute relative path; can't use os.path.relpath() here as it returns "." instead of "" + rel_path = root[len(input_folder):] + if rel_path[:1] == os.sep: + rel_path = rel_path[1:] + + for f in files + [self.kw['index_file']]: + rel_name = os.path.join(rel_path, f) + rel_output_name = os.path.join(output_folder, rel_path, f) + # Register file names in the mapping. + self.register_output_name(input_folder, rel_name, rel_output_name) + return super(Listings, self).set_site(site) def gen_tasks(self): """Render pretty code listings.""" - kw = { - "default_lang": self.site.config["DEFAULT_LANG"], - "listings_folder": self.site.config["LISTINGS_FOLDER"], - "output_folder": self.site.config["OUTPUT_FOLDER"], - "index_file": self.site.config["INDEX_FILE"], - } # Things to ignore in listings ignored_extensions = (".pyc", ".pyo") - def render_listing(in_name, out_name, folders=[], files=[]): + def render_listing(in_name, out_name, input_folder, output_folder, folders=[], files=[]): if in_name: with open(in_name, 'r') as fd: try: lexer = get_lexer_for_filename(in_name) except: lexer = TextLexer() - code = highlight(fd.read(), lexer, - HtmlFormatter(cssclass='code', - linenos="table", nowrap=False, - lineanchors=utils.slugify(in_name, force=True), - anchorlinenos=True)) - # the pygments highlighter uses <div class="codehilite"><pre> - # for code. We switch it to reST's <pre class="code">. - code = CODERE.sub('<pre class="code literal-block">\\1</pre>', code) + code = highlight(fd.read(), lexer, utils.NikolaPygmentsHTML(in_name)) title = os.path.basename(in_name) else: code = '' - title = '' + title = os.path.split(os.path.dirname(out_name))[1] crumbs = utils.get_crumbs(os.path.relpath(out_name, - kw['output_folder']), + self.kw['output_folder']), is_file=True) permalink = self.site.link( 'listing', - os.path.relpath( - out_name, - os.path.join( - kw['output_folder'], - kw['listings_folder']))) - if self.site.config['COPY_SOURCES']: - source_link = permalink[:-5] + os.path.join( + input_folder, + os.path.relpath( + out_name[:-5], # remove '.html' + os.path.join( + self.kw['output_folder'], + output_folder)))) + if self.site.config['COPY_SOURCES'] and in_name: + source_link = permalink[:-5] # remove '.html' else: source_link = None context = { @@ -101,88 +142,121 @@ class Listings(Task): 'title': title, 'crumbs': crumbs, 'permalink': permalink, - 'lang': kw['default_lang'], - 'folders': natsort.natsorted(folders), - 'files': natsort.natsorted(files), + 'lang': self.kw['default_lang'], + 'folders': natsort.natsorted( + folders, alg=natsort.ns.F | natsort.ns.IC), + 'files': natsort.natsorted( + files, alg=natsort.ns.F | natsort.ns.IC), 'description': title, 'source_link': source_link, } - self.site.render_template('listing.tmpl', out_name, - context) + self.site.render_template('listing.tmpl', out_name, context) yield self.group_task() template_deps = self.site.template_system.template_deps('listing.tmpl') - for root, dirs, files in os.walk(kw['listings_folder'], followlinks=True): - files = [f for f in files if os.path.splitext(f)[-1] not in ignored_extensions] - - uptodate = {'c': self.site.GLOBAL_CONTEXT} - - for k, v in self.site.GLOBAL_CONTEXT['template_hooks'].items(): - uptodate['||template_hooks|{0}||'.format(k)] = v._items - - for k in self.site._GLOBAL_CONTEXT_TRANSLATABLE: - uptodate[k] = self.site.GLOBAL_CONTEXT[k](kw['default_lang']) - - # save navigation links as dependencies - uptodate['navigation_links'] = uptodate['c']['navigation_links'](kw['default_lang']) - - uptodate2 = uptodate.copy() - uptodate2['f'] = files - uptodate2['d'] = dirs - - # Render all files - out_name = os.path.join( - kw['output_folder'], - root, kw['index_file'] - ) - yield { - 'basename': self.name, - 'name': out_name, - 'file_dep': template_deps, - 'targets': [out_name], - 'actions': [(render_listing, [None, out_name, dirs, files])], - # This is necessary to reflect changes in blog title, - # sidebar links, etc. - 'uptodate': [utils.config_changed(uptodate2)], - 'clean': True, - } - for f in files: - ext = os.path.splitext(f)[-1] - if ext in ignored_extensions: - continue - in_name = os.path.join(root, f) - out_name = os.path.join( - kw['output_folder'], - root, - f) + '.html' - yield { + + for input_folder, output_folder in self.kw['listings_folders'].items(): + for root, dirs, files in os.walk(input_folder, followlinks=True): + files = [f for f in files if os.path.splitext(f)[-1] not in ignored_extensions] + + uptodate = {'c': self.site.GLOBAL_CONTEXT} + + for k, v in self.site.GLOBAL_CONTEXT['template_hooks'].items(): + uptodate['||template_hooks|{0}||'.format(k)] = v._items + + for k in self.site._GLOBAL_CONTEXT_TRANSLATABLE: + uptodate[k] = self.site.GLOBAL_CONTEXT[k](self.kw['default_lang']) + + # save navigation links as dependencies + uptodate['navigation_links'] = uptodate['c']['navigation_links'](self.kw['default_lang']) + + uptodate['kw'] = self.kw + + uptodate2 = uptodate.copy() + uptodate2['f'] = files + uptodate2['d'] = dirs + + # Compute relative path; can't use os.path.relpath() here as it returns "." instead of "" + rel_path = root[len(input_folder):] + if rel_path[:1] == os.sep: + rel_path = rel_path[1:] + + rel_name = os.path.join(rel_path, self.kw['index_file']) + rel_output_name = os.path.join(output_folder, rel_path, self.kw['index_file']) + + # Render all files + out_name = os.path.join(self.kw['output_folder'], rel_output_name) + yield utils.apply_filters({ 'basename': self.name, 'name': out_name, - 'file_dep': template_deps + [in_name], + 'file_dep': template_deps, 'targets': [out_name], - 'actions': [(render_listing, [in_name, out_name])], + 'actions': [(render_listing, [None, out_name, input_folder, output_folder, dirs, files])], # This is necessary to reflect changes in blog title, # sidebar links, etc. - 'uptodate': [utils.config_changed(uptodate)], + 'uptodate': [utils.config_changed(uptodate2, 'nikola.plugins.task.listings:folder')], 'clean': True, - } - if self.site.config['COPY_SOURCES']: - out_name = os.path.join( - kw['output_folder'], - root, - f) - yield { + }, self.kw["filters"]) + for f in files: + ext = os.path.splitext(f)[-1] + if ext in ignored_extensions: + continue + in_name = os.path.join(root, f) + # Record file names + rel_name = os.path.join(rel_path, f + '.html') + rel_output_name = os.path.join(output_folder, rel_path, f + '.html') + self.register_output_name(input_folder, rel_name, rel_output_name) + # Set up output name + out_name = os.path.join(self.kw['output_folder'], rel_output_name) + # Yield task + yield utils.apply_filters({ 'basename': self.name, 'name': out_name, - 'file_dep': [in_name], + 'file_dep': template_deps + [in_name], 'targets': [out_name], - 'actions': [(utils.copy_file, [in_name, out_name])], + 'actions': [(render_listing, [in_name, out_name, input_folder, output_folder])], + # This is necessary to reflect changes in blog title, + # sidebar links, etc. + 'uptodate': [utils.config_changed(uptodate, 'nikola.plugins.task.listings:source')], 'clean': True, - } + }, self.kw["filters"]) + if self.site.config['COPY_SOURCES']: + rel_name = os.path.join(rel_path, f) + rel_output_name = os.path.join(output_folder, rel_path, f) + self.register_output_name(input_folder, rel_name, rel_output_name) + out_name = os.path.join(self.kw['output_folder'], rel_output_name) + yield utils.apply_filters({ + 'basename': self.name, + 'name': out_name, + 'file_dep': [in_name], + 'targets': [out_name], + 'actions': [(utils.copy_file, [in_name, out_name])], + 'clean': True, + }, self.kw["filters"]) - def listing_path(self, name, lang): - if not name.endswith('.html'): + def listing_path(self, namep, lang): + namep = namep.replace('/', os.sep) + nameh = namep + '.html' + for name in (namep, nameh): + if name in self.proper_input_file_mapping: + # If the name shows up in this dict, everything's fine. + name = self.proper_input_file_mapping[name] + break + elif name in self.improper_input_file_mapping: + # If the name shows up in this dict, we have to check for + # ambiguities. + if len(self.improper_input_file_mapping[name]) > 1: + utils.LOGGER.error("Using non-unique listing name '{0}', which maps to more than one listing name ({1})!".format(name, str(self.improper_input_file_mapping[name]))) + sys.exit(1) + if len(self.site.config['LISTINGS_FOLDERS']) > 1: + utils.LOGGER.notice("Using listings names in site.link() without input directory prefix while configuration's LISTINGS_FOLDERS has more than one entry.") + name = self.improper_input_file_mapping[name][0] + break + else: + utils.LOGGER.error("Unknown listing name {0}!".format(namep)) + sys.exit(1) + if not name.endswith(os.sep + self.site.config["INDEX_FILE"]): name += '.html' - path_parts = [self.site.config['LISTINGS_FOLDER']] + list(os.path.split(name)) + path_parts = name.split(os.sep) return [_f for _f in path_parts if _f] diff --git a/nikola/plugins/task/pages.plugin b/nikola/plugins/task/pages.plugin index 67212d2..4cad7b7 100644 --- a/nikola/plugins/task/pages.plugin +++ b/nikola/plugins/task/pages.plugin @@ -4,7 +4,7 @@ Module = pages [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Create pages in the output. diff --git a/nikola/plugins/task/pages.py b/nikola/plugins/task/pages.py index aefc5a1..d0edb56 100644 --- a/nikola/plugins/task/pages.py +++ b/nikola/plugins/task/pages.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -51,9 +51,7 @@ class RenderPages(Task): continue for task in self.site.generic_page_renderer(lang, post, kw["filters"]): - task['uptodate'] = [config_changed({ - 1: task['uptodate'][0].config, - 2: kw})] + task['uptodate'] = task['uptodate'] + [config_changed(kw, 'nikola.plugins.task.pages')] task['basename'] = self.name task['task_dep'] = ['render_posts'] yield task diff --git a/nikola/plugins/task/posts.plugin b/nikola/plugins/task/posts.plugin index e1a42fd..707b3c2 100644 --- a/nikola/plugins/task/posts.plugin +++ b/nikola/plugins/task/posts.plugin @@ -4,7 +4,7 @@ Module = posts [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Create HTML fragments out of posts. diff --git a/nikola/plugins/task/posts.py b/nikola/plugins/task/posts.py index 8e03122..d3f17fd 100644 --- a/nikola/plugins/task/posts.py +++ b/nikola/plugins/task/posts.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -25,18 +25,20 @@ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from copy import copy +import os from nikola.plugin_categories import Task -from nikola import utils +from nikola import filters, utils -def rest_deps(post, task): - """Add extra_deps from ReST into task. +def update_deps(post, lang, task): + """Updates file dependencies as they might have been updated during compilation. - The .dep file is created by ReST so not available before the task starts - to execute. + This is done for example by the ReST page compiler, which writes its + dependencies into a .dep file. This file is read and incorporated when calling + post.fragment_deps(), and only available /after/ compiling the fragment. """ - task.file_dep.update(post.extra_deps()) + task.file_dep.update([p for p in post.fragment_deps(lang) if not p.startswith("####MAGIC####")]) class RenderPosts(Task): @@ -54,23 +56,62 @@ class RenderPosts(Task): "show_untranslated_posts": self.site.config['SHOW_UNTRANSLATED_POSTS'], "demote_headers": self.site.config['DEMOTE_HEADERS'], } + self.tl_changed = False yield self.group_task() + def tl_ch(): + self.tl_changed = True + + yield { + 'basename': self.name, + 'name': 'timeline_changes', + 'actions': [tl_ch], + 'uptodate': [utils.config_changed({1: kw['timeline']})], + } + for lang in kw["translations"]: deps_dict = copy(kw) deps_dict.pop('timeline') for post in kw['timeline']: + dest = post.translated_base_path(lang) + file_dep = [p for p in post.fragment_deps(lang) if not p.startswith("####MAGIC####")] task = { 'basename': self.name, 'name': dest, - 'file_dep': post.fragment_deps(lang), + 'file_dep': file_dep, 'targets': [dest], 'actions': [(post.compile, (lang, )), - (rest_deps, (post,)), + (update_deps, (post, lang, )), ], 'clean': True, - 'uptodate': [utils.config_changed(deps_dict)], + 'uptodate': [ + utils.config_changed(deps_dict, 'nikola.plugins.task.posts'), + lambda p=post, l=lang: self.dependence_on_timeline(p, l) + ] + post.fragment_deps_uptodate(lang), + 'task_dep': ['render_posts:timeline_changes'] } - yield task + + # Apply filters specified in the metadata + ff = [x.strip() for x in post.meta('filters', lang).split(',')] + flist = [] + for i, f in enumerate(ff): + if not f: + continue + if f.startswith('filters.'): # A function from the filters module + f = f[8:] + try: + flist.append(getattr(filters, f)) + except AttributeError: + pass + else: + flist.append(f) + yield utils.apply_filters(task, {os.path.splitext(dest): flist}) + + def dependence_on_timeline(self, post, lang): + if "####MAGIC####TIMELINE" not in post.fragment_deps(lang): + return True # No dependency on timeline + elif self.tl_changed: + return False # Timeline changed + return True diff --git a/nikola/plugins/task/redirect.plugin b/nikola/plugins/task/redirect.plugin index 826f3d8..0228c70 100644 --- a/nikola/plugins/task/redirect.plugin +++ b/nikola/plugins/task/redirect.plugin @@ -4,7 +4,7 @@ Module = redirect [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Create redirect pages. diff --git a/nikola/plugins/task/redirect.py b/nikola/plugins/task/redirect.py index e1134bf..428dd5a 100644 --- a/nikola/plugins/task/redirect.py +++ b/nikola/plugins/task/redirect.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -24,7 +24,8 @@ # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -import io +from __future__ import unicode_literals + import os from nikola.plugin_categories import Task @@ -42,26 +43,18 @@ class Redirect(Task): kw = { 'redirections': self.site.config['REDIRECTIONS'], 'output_folder': self.site.config['OUTPUT_FOLDER'], + 'filters': self.site.config['FILTERS'], } yield self.group_task() if kw['redirections']: for src, dst in kw["redirections"]: src_path = os.path.join(kw["output_folder"], src) - yield { + yield utils.apply_filters({ 'basename': self.name, 'name': src_path, 'targets': [src_path], - 'actions': [(create_redirect, (src_path, dst))], + 'actions': [(utils.create_redirect, (src_path, dst))], 'clean': True, - 'uptodate': [utils.config_changed(kw)], - } - - -def create_redirect(src, dst): - utils.makedirs(os.path.dirname(src)) - with io.open(src, "w+", encoding="utf8") as fd: - fd.write('<!DOCTYPE html><head><title>Redirecting...</title>' - '<meta name="robots" content="noindex">' - '<meta http-equiv="refresh" content="0; ' - 'url={0}"></head><body><p>Page moved <a href="{0}">here</a></p></body>'.format(dst)) + 'uptodate': [utils.config_changed(kw, 'nikola.plugins.task.redirect')], + }, kw["filters"]) diff --git a/nikola/plugins/task/robots.plugin b/nikola/plugins/task/robots.plugin index 60b50fb..b4b43a3 100644 --- a/nikola/plugins/task/robots.plugin +++ b/nikola/plugins/task/robots.plugin @@ -4,7 +4,7 @@ Module = robots [Documentation] Author = Daniel Aleksandersen -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Generate /robots.txt exclusion file and promote sitemap. diff --git a/nikola/plugins/task/robots.py b/nikola/plugins/task/robots.py index b229d37..2f25a21 100644 --- a/nikola/plugins/task/robots.py +++ b/nikola/plugins/task/robots.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -48,7 +48,8 @@ class RobotsFile(LateTask): "site_url": self.site.config["SITE_URL"], "output_folder": self.site.config["OUTPUT_FOLDER"], "files_folders": self.site.config['FILES_FOLDERS'], - "robots_exclusions": self.site.config["ROBOTS_EXCLUSIONS"] + "robots_exclusions": self.site.config["ROBOTS_EXCLUSIONS"], + "filters": self.site.config["FILTERS"], } sitemapindex_url = urljoin(kw["base_url"], "sitemapindex.xml") @@ -68,15 +69,15 @@ class RobotsFile(LateTask): yield self.group_task() if not utils.get_asset_path("robots.txt", [], files_folders=kw["files_folders"]): - yield { + yield utils.apply_filters({ "basename": self.name, "name": robots_path, "targets": [robots_path], "actions": [(write_robots)], - "uptodate": [utils.config_changed(kw)], + "uptodate": [utils.config_changed(kw, 'nikola.plugins.task.robots')], "clean": True, "task_dep": ["sitemap"] - } + }, kw["filters"]) elif kw["robots_exclusions"]: utils.LOGGER.warn('Did not generate robots.txt as one already exists in FILES_FOLDERS. ROBOTS_EXCLUSIONS will not have any affect on the copied fie.') else: diff --git a/nikola/plugins/task/rss.plugin b/nikola/plugins/task/rss.plugin index 7206a43..56f0bf4 100644 --- a/nikola/plugins/task/rss.plugin +++ b/nikola/plugins/task/rss.plugin @@ -4,7 +4,7 @@ Module = rss [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Generate RSS feeds. diff --git a/nikola/plugins/task/rss.py b/nikola/plugins/task/rss.py index b16ed48..26a4da1 100644 --- a/nikola/plugins/task/rss.py +++ b/nikola/plugins/task/rss.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -51,6 +51,7 @@ class GenerateRSS(Task): "filters": self.site.config["FILTERS"], "blog_title": self.site.config["BLOG_TITLE"], "site_url": self.site.config["SITE_URL"], + "base_url": self.site.config["BASE_URL"], "blog_description": self.site.config["BLOG_DESCRIPTION"], "output_folder": self.site.config["OUTPUT_FOLDER"], "rss_teasers": self.site.config["RSS_TEASERS"], @@ -59,6 +60,7 @@ class GenerateRSS(Task): "feed_length": self.site.config['FEED_LENGTH'], "tzinfo": self.site.tzinfo, "rss_read_more_link": self.site.config["RSS_READ_MORE_LINK"], + "rss_links_append_query": self.site.config["RSS_LINKS_APPEND_QUERY"], } self.site.scan_posts() # Check for any changes in the state of use_in_feeds for any post. @@ -71,16 +73,18 @@ class GenerateRSS(Task): output_name = os.path.join(kw['output_folder'], self.site.path("rss", None, lang)) deps = [] + deps_uptodate = [] if kw["show_untranslated_posts"]: - posts = self.site.posts[:10] + posts = self.site.posts[:kw['feed_length']] else: - posts = [x for x in self.site.posts if x.is_translation_available(lang)][:10] + posts = [x for x in self.site.posts if x.is_translation_available(lang)][:kw['feed_length']] for post in posts: deps += post.deps(lang) + deps_uptodate += post.deps_uptodate(lang) feed_url = urljoin(self.site.config['BASE_URL'], self.site.link("rss", None, lang).lstrip('/')) - yield { + task = { 'basename': 'generate_rss', 'name': os.path.normpath(output_name), 'file_dep': deps, @@ -88,12 +92,14 @@ class GenerateRSS(Task): 'actions': [(utils.generic_rss_renderer, (lang, kw["blog_title"](lang), kw["site_url"], kw["blog_description"](lang), posts, output_name, - kw["rss_teasers"], kw["rss_plain"], kw['feed_length'], feed_url))], + kw["rss_teasers"], kw["rss_plain"], kw['feed_length'], feed_url, + None, kw["rss_links_append_query"]))], 'task_dep': ['render_posts'], 'clean': True, - 'uptodate': [utils.config_changed(kw)], + 'uptodate': [utils.config_changed(kw, 'nikola.plugins.task.rss')] + deps_uptodate, } + yield utils.apply_filters(task, kw['filters']) def rss_path(self, name, lang): return [_f for _f in [self.site.config['TRANSLATIONS'][lang], diff --git a/nikola/plugins/task/scale_images.plugin b/nikola/plugins/task/scale_images.plugin new file mode 100644 index 0000000..c0f0f28 --- /dev/null +++ b/nikola/plugins/task/scale_images.plugin @@ -0,0 +1,9 @@ +[Core] +Name = scale_images +Module = scale_images + +[Documentation] +Author = Pelle Nilsson +Version = 1.0 +Website = http://getnikola.com +Description = Create down-scaled images and thumbnails. diff --git a/nikola/plugins/task/scale_images.py b/nikola/plugins/task/scale_images.py new file mode 100644 index 0000000..f97027e --- /dev/null +++ b/nikola/plugins/task/scale_images.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- + +# Copyright © 2014-2015 Pelle Nilsson and others. + +# 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. + +import os + +from nikola.plugin_categories import Task +from nikola.image_processing import ImageProcessor +from nikola import utils + + +class ScaleImage(Task, ImageProcessor): + """Copy static files into the output folder.""" + + name = "scale_images" + + def set_site(self, site): + self.logger = utils.get_logger('scale_images', site.loghandlers) + return super(ScaleImage, self).set_site(site) + + def process_tree(self, src, dst): + """Processes all images in a src tree and put the (possibly) rescaled + images in the dst folder.""" + ignore = set(['.svn']) + base_len = len(src.split(os.sep)) + for root, dirs, files in os.walk(src, followlinks=True): + root_parts = root.split(os.sep) + if set(root_parts) & ignore: + continue + dst_dir = os.path.join(dst, *root_parts[base_len:]) + utils.makedirs(dst_dir) + for src_name in files: + if src_name in ('.DS_Store', 'Thumbs.db'): + continue + if (not src_name.lower().endswith(tuple(self.image_ext_list)) and not src_name.upper().endswith(tuple(self.image_ext_list))): + continue + dst_file = os.path.join(dst_dir, src_name) + src_file = os.path.join(root, src_name) + thumb_file = '.thumbnail'.join(os.path.splitext(dst_file)) + yield { + 'name': dst_file, + 'file_dep': [src_file], + 'targets': [dst_file, thumb_file], + 'actions': [(self.process_image, (src_file, dst_file, thumb_file))], + 'clean': True, + } + + def process_image(self, src, dst, thumb): + self.resize_image(src, dst, self.kw['max_image_size'], False) + self.resize_image(src, thumb, self.kw['image_thumbnail_size'], False) + + def gen_tasks(self): + """Copy static files into the output folder.""" + + self.kw = { + 'image_thumbnail_size': self.site.config['IMAGE_THUMBNAIL_SIZE'], + 'max_image_size': self.site.config['MAX_IMAGE_SIZE'], + 'image_folders': self.site.config['IMAGE_FOLDERS'], + 'output_folder': self.site.config['OUTPUT_FOLDER'], + 'filters': self.site.config['FILTERS'], + } + + self.image_ext_list = self.image_ext_list_builtin + self.image_ext_list.extend(self.site.config.get('EXTRA_IMAGE_EXTENSIONS', [])) + + yield self.group_task() + for src in self.kw['image_folders']: + dst = self.kw['output_folder'] + filters = self.kw['filters'] + real_dst = os.path.join(dst, self.kw['image_folders'][src]) + for task in self.process_tree(src, real_dst): + task['basename'] = self.name + task['uptodate'] = [utils.config_changed(self.kw)] + yield utils.apply_filters(task, filters) diff --git a/nikola/plugins/task/sitemap.plugin b/nikola/plugins/task/sitemap.plugin index 2cd8195..0b992b8 100644 --- a/nikola/plugins/task/sitemap.plugin +++ b/nikola/plugins/task/sitemap.plugin @@ -4,7 +4,7 @@ Module = sitemap [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Generate google sitemap. diff --git a/nikola/plugins/task/sitemap/__init__.py b/nikola/plugins/task/sitemap/__init__.py index 943e9b2..92d557d 100644 --- a/nikola/plugins/task/sitemap/__init__.py +++ b/nikola/plugins/task/sitemap/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -36,7 +36,7 @@ except ImportError: import urllib.robotparser as robotparser # NOQA from nikola.plugin_categories import LateTask -from nikola.utils import config_changed +from nikola.utils import config_changed, apply_filters urlset_header = """<?xml version="1.0" encoding="UTF-8"?> @@ -49,7 +49,7 @@ urlset_header = """<?xml version="1.0" encoding="UTF-8"?> loc_format = """ <url> <loc>{0}</loc> - <lastmod>{1}</lastmod> + <lastmod>{1}</lastmod>{2} </url> """ @@ -69,6 +69,9 @@ sitemap_format = """ <sitemap> </sitemap> """ +alternates_format = """\n <xhtml:link rel="alternate" hreflang="{0}" href="{1}" />""" + + sitemapindex_footer = "</sitemapindex>" @@ -111,8 +114,10 @@ class Sitemap(LateTask): "strip_indexes": self.site.config["STRIP_INDEXES"], "index_file": self.site.config["INDEX_FILE"], "sitemap_include_fileless_dirs": self.site.config["SITEMAP_INCLUDE_FILELESS_DIRS"], - "mapped_extensions": self.site.config.get('MAPPED_EXTENSIONS', ['.html', '.htm', '.xml', '.rss']), - "robots_exclusions": self.site.config["ROBOTS_EXCLUSIONS"] + "mapped_extensions": self.site.config.get('MAPPED_EXTENSIONS', ['.atom', '.html', '.htm', '.xml', '.rss']), + "robots_exclusions": self.site.config["ROBOTS_EXCLUSIONS"], + "filters": self.site.config["FILTERS"], + "translations": self.site.config["TRANSLATIONS"], } output = kw['output_folder'] @@ -136,7 +141,17 @@ class Sitemap(LateTask): lastmod = self.get_lastmod(root) loc = urljoin(base_url, base_path + path) if kw['index_file'] in files and kw['strip_indexes']: # ignore folders when not stripping urls - urlset[loc] = loc_format.format(loc, lastmod) + post = self.site.post_per_file.get(path + kw['index_file']) + if post and (post.is_draft or post.is_private or post.publish_later): + continue + alternates = [] + if post: + for lang in kw['translations']: + alt_url = post.permalink(lang=lang, absolute=True) + if loc == alt_url: + continue + alternates.append(alternates_format.format(lang, alt_url)) + urlset[loc] = loc_format.format(loc, lastmod, ''.join(alternates)) for fname in files: if kw['strip_indexes'] and fname == kw['index_file']: continue # We already mapped the folder @@ -148,20 +163,30 @@ class Sitemap(LateTask): continue if not robot_fetch(path): continue + + # read in binary mode to make ancient files work + fh = open(real_path, 'rb') + filehead = fh.read(1024) + fh.close() + if path.endswith('.html') or path.endswith('.htm'): - try: - if u'<!doctype html' not in io.open(real_path, 'r', encoding='utf8').read(1024).lower(): - # ignores "html" files without doctype - # alexa-verify, google-site-verification, etc. - continue - except UnicodeDecodeError: - # ignore ancient files - # most non-utf8 files are worthless anyways + """ ignores "html" files without doctype """ + if b'<!doctype html' not in filehead.lower(): continue - """ put RSS in sitemapindex[] instead of in urlset[], sitemap_path is included after it is generated """ - if path.endswith('.xml') or path.endswith('.rss'): - filehead = io.open(real_path, 'r', encoding='utf8').read(512) - if u'<rss' in filehead or (u'<urlset' in filehead and path != sitemap_path): + + """ ignores "html" files with noindex robot directives """ + robots_directives = [b'<meta content="noindex" name="robots"', + b'<meta content="none" name="robots"', + b'<meta name="robots" content="noindex"', + b'<meta name="robots" content="none"'] + if any([robot_directive in filehead.lower() for robot_directive in robots_directives]): + continue + + # put Atom and RSS in sitemapindex[] instead of in urlset[], + # sitemap_path is included after it is generated + if path.endswith('.xml') or path.endswith('.atom') or path.endswith('.rss'): + known_elm_roots = (b'<feed', b'<rss', b'<urlset') + if any([elm_root in filehead.lower() for elm_root in known_elm_roots]) and path != sitemap_path: path = path.replace(os.sep, '/') lastmod = self.get_lastmod(real_path) loc = urljoin(base_url, base_path + path) @@ -175,7 +200,14 @@ class Sitemap(LateTask): path = path.replace(os.sep, '/') lastmod = self.get_lastmod(real_path) loc = urljoin(base_url, base_path + path) - urlset[loc] = loc_format.format(loc, lastmod) + alternates = [] + if post: + for lang in kw['translations']: + alt_url = post.permalink(lang=lang, absolute=True) + if loc == alt_url: + continue + alternates.append(alternates_format.format(lang, alt_url)) + urlset[loc] = loc_format.format(loc, lastmod, '\n'.join(alternates)) def robot_fetch(path): for rule in kw["robots_exclusions"]: @@ -208,7 +240,27 @@ class Sitemap(LateTask): # to scan locations. def scan_locs_task(): scan_locs() - return {'locations': list(urlset.keys()) + list(sitemapindex.keys())} + + # Generate a list of file dependencies for the actual generation + # task, so rebuilds are triggered. (Issue #1032) + output = kw["output_folder"] + file_dep = [] + + for i in urlset.keys(): + p = os.path.join(output, urlparse(i).path.replace(base_path, '', 1)) + if not p.endswith('sitemap.xml') and not os.path.isdir(p): + file_dep.append(p) + if os.path.isdir(p) and os.path.exists(os.path.join(p, 'index.html')): + file_dep.append(p + 'index.html') + + for i in sitemapindex.keys(): + p = os.path.join(output, urlparse(i).path.replace(base_path, '', 1)) + if not p.endswith('sitemap.xml') and not os.path.isdir(p): + file_dep.append(p) + if os.path.isdir(p) and os.path.exists(os.path.join(p, 'index.html')): + file_dep.append(p + 'index.html') + + return {'file_dep': file_dep} yield { "basename": "_scan_locs", @@ -217,29 +269,29 @@ class Sitemap(LateTask): } yield self.group_task() - yield { + yield apply_filters({ "basename": "sitemap", "name": sitemap_path, "targets": [sitemap_path], "actions": [(write_sitemap,)], - "uptodate": [config_changed(kw)], + "uptodate": [config_changed(kw, 'nikola.plugins.task.sitemap:write')], "clean": True, "task_dep": ["render_site"], "calc_dep": ["_scan_locs:sitemap"], - } - yield { + }, kw['filters']) + yield apply_filters({ "basename": "sitemap", "name": sitemapindex_path, "targets": [sitemapindex_path], "actions": [(write_sitemapindex,)], - "uptodate": [config_changed(kw)], + "uptodate": [config_changed(kw, 'nikola.plugins.task.sitemap:write_index')], "clean": True, "file_dep": [sitemap_path] - } + }, kw['filters']) def get_lastmod(self, p): if self.site.invariant: - return '2014-01-01' + return '2038-01-01' else: return datetime.datetime.fromtimestamp(os.stat(p).st_mtime).isoformat().split('T')[0] diff --git a/nikola/plugins/task/sources.plugin b/nikola/plugins/task/sources.plugin index 6224e48..5560df6 100644 --- a/nikola/plugins/task/sources.plugin +++ b/nikola/plugins/task/sources.plugin @@ -4,7 +4,7 @@ Module = sources [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Copy page sources into the output. diff --git a/nikola/plugins/task/sources.py b/nikola/plugins/task/sources.py index 4c669c2..840a31c 100644 --- a/nikola/plugins/task/sources.py +++ b/nikola/plugins/task/sources.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -49,6 +49,7 @@ class Sources(Task): "translations": self.site.config["TRANSLATIONS"], "output_folder": self.site.config["OUTPUT_FOLDER"], "default_lang": self.site.config["DEFAULT_LANG"], + "show_untranslated_posts": self.site.config['SHOW_UNTRANSLATED_POSTS'], } self.site.scan_posts() @@ -56,6 +57,8 @@ class Sources(Task): if self.site.config['COPY_SOURCES']: for lang in kw["translations"]: for post in self.site.timeline: + if not kw["show_untranslated_posts"] and lang not in post.translated_to: + continue if post.meta('password'): continue output_name = os.path.join( @@ -77,5 +80,5 @@ class Sources(Task): 'targets': [output_name], 'actions': [(utils.copy_file, (source, output_name))], 'clean': True, - 'uptodate': [utils.config_changed(kw)], + 'uptodate': [utils.config_changed(kw, 'nikola.plugins.task.sources')], } diff --git a/nikola/plugins/task/tags.plugin b/nikola/plugins/task/tags.plugin index f01e0f8..4ac3800 100644 --- a/nikola/plugins/task/tags.plugin +++ b/nikola/plugins/task/tags.plugin @@ -4,7 +4,7 @@ Module = tags [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Render the tag pages and feeds. diff --git a/nikola/plugins/task/tags.py b/nikola/plugins/task/tags.py index 8d43f13..832ceff 100644 --- a/nikola/plugins/task/tags.py +++ b/nikola/plugins/task/tags.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -27,6 +27,8 @@ from __future__ import unicode_literals import json import os +import sys +import natsort try: from urlparse import urljoin except ImportError: @@ -43,9 +45,12 @@ class RenderTags(Task): def set_site(self, site): site.register_path_handler('tag_index', self.tag_index_path) + site.register_path_handler('category_index', self.category_index_path) site.register_path_handler('tag', self.tag_path) + site.register_path_handler('tag_atom', self.tag_atom_path) site.register_path_handler('tag_rss', self.tag_rss_path) site.register_path_handler('category', self.category_path) + site.register_path_handler('category_atom', self.category_atom_path) site.register_path_handler('category_rss', self.category_rss_path) return super(RenderTags, self).set_site(site) @@ -56,18 +61,26 @@ class RenderTags(Task): "translations": self.site.config["TRANSLATIONS"], "blog_title": self.site.config["BLOG_TITLE"], "site_url": self.site.config["SITE_URL"], + "base_url": self.site.config["BASE_URL"], "messages": self.site.MESSAGES, "output_folder": self.site.config['OUTPUT_FOLDER'], "filters": self.site.config['FILTERS'], + 'tag_path': self.site.config['TAG_PATH'], "tag_pages_are_indexes": self.site.config['TAG_PAGES_ARE_INDEXES'], - "index_display_post_count": self.site.config['INDEX_DISPLAY_POST_COUNT'], - "index_teasers": self.site.config['INDEX_TEASERS'], + 'category_path': self.site.config['CATEGORY_PATH'], + 'category_prefix': self.site.config['CATEGORY_PREFIX'], + "category_pages_are_indexes": self.site.config['CATEGORY_PAGES_ARE_INDEXES'], "generate_rss": self.site.config['GENERATE_RSS'], "rss_teasers": self.site.config["RSS_TEASERS"], "rss_plain": self.site.config["RSS_PLAIN"], + "rss_link_append_query": self.site.config["RSS_LINKS_APPEND_QUERY"], "show_untranslated_posts": self.site.config['SHOW_UNTRANSLATED_POSTS'], "feed_length": self.site.config['FEED_LENGTH'], + "taglist_minimum_post_count": self.site.config['TAGLIST_MINIMUM_POSTS'], "tzinfo": self.site.tzinfo, + "pretty_urls": self.site.config['PRETTY_URLS'], + "strip_indexes": self.site.config['STRIP_INDEXES'], + "index_file": self.site.config['INDEX_FILE'], } self.site.scan_posts() @@ -78,6 +91,32 @@ class RenderTags(Task): if not self.site.posts_per_tag and not self.site.posts_per_category: return + if kw['category_path'] == kw['tag_path']: + tags = {self.slugify_tag_name(tag): tag for tag in self.site.posts_per_tag.keys()} + cats = {tuple(self.slugify_category_name(category)): category for category in self.site.posts_per_category.keys()} + categories = {k[0]: v for k, v in cats.items() if len(k) == 1} + intersect = set(tags.keys()) & set(categories.keys()) + if len(intersect) > 0: + for slug in intersect: + utils.LOGGER.error("Category '{0}' and tag '{1}' both have the same slug '{2}'!".format('/'.join(categories[slug]), tags[slug], slug)) + sys.exit(1) + + # Test for category slug clashes + categories = {} + for category in self.site.posts_per_category.keys(): + slug = tuple(self.slugify_category_name(category)) + for part in slug: + if len(part) == 0: + utils.LOGGER.error("Category '{0}' yields invalid slug '{1}'!".format(category, '/'.join(slug))) + sys.exit(1) + if slug in categories: + other_category = categories[slug] + utils.LOGGER.error('You have categories that are too similar: {0} and {1}'.format(category, other_category)) + utils.LOGGER.error('Category {0} is used in: {1}'.format(category, ', '.join([p.source_path for p in self.site.posts_per_category[category]]))) + utils.LOGGER.error('Category {0} is used in: {1}'.format(other_category, ', '.join([p.source_path for p in self.site.posts_per_category[other_category]]))) + sys.exit(1) + categories[slug] = category + tag_list = list(self.site.posts_per_tag.items()) cat_list = list(self.site.posts_per_category.items()) @@ -92,7 +131,7 @@ class RenderTags(Task): if kw["generate_rss"]: yield self.tag_rss(tag, lang, filtered_posts, kw, is_category) # Render HTML - if kw['tag_pages_are_indexes']: + if kw['category_pages_are_indexes'] if is_category else kw['tag_pages_are_indexes']: yield self.tag_page_as_index(tag, lang, filtered_posts, kw, is_category) else: yield self.tag_page_as_list(tag, lang, filtered_posts, kw, is_category) @@ -101,19 +140,19 @@ class RenderTags(Task): for task in render_lists(tag, posts, False): yield task - for tag, posts in cat_list: - if tag == '': # This is uncategorized posts - continue - for task in render_lists(tag, posts, True): + for path, posts in cat_list: + for task in render_lists(path, posts, True): yield task # Tag cloud json file tag_cloud_data = {} for tag, posts in self.site.posts_per_tag.items(): + if tag in self.site.config['HIDDEN_TAGS']: + continue tag_posts = dict(posts=[{'title': post.meta[post.default_lang]['title'], 'date': post.date.strftime('%m/%d/%Y'), 'isodate': post.date.isoformat(), - 'url': post.base_path.replace('cache', '')} + 'url': post.permalink(post.default_lang)} for post in reversed(sorted(self.site.timeline, key=lambda post: post.date)) if tag in post.alltags]) tag_cloud_data[tag] = [len(posts), self.site.link( @@ -126,48 +165,59 @@ class RenderTags(Task): with open(output_name, 'w+') as fd: json.dump(data, fd) - task = { - 'basename': str(self.name), - 'name': str(output_name) - } + if self.site.config['WRITE_TAG_CLOUD']: + task = { + 'basename': str(self.name), + 'name': str(output_name) + } - task['uptodate'] = [utils.config_changed(tag_cloud_data)] - task['targets'] = [output_name] - task['actions'] = [(write_tag_data, [tag_cloud_data])] - task['clean'] = True - yield task + task['uptodate'] = [utils.config_changed(tag_cloud_data, 'nikola.plugins.task.tags:tagdata')] + task['targets'] = [output_name] + task['actions'] = [(write_tag_data, [tag_cloud_data])] + task['clean'] = True + yield utils.apply_filters(task, kw['filters']) - def list_tags_page(self, kw): + def _create_tags_page(self, kw, include_tags=True, include_categories=True): """a global "all your tags/categories" page for each language""" - tags = list(self.site.posts_per_tag.keys()) - categories = list(self.site.posts_per_category.keys()) - # We want our tags to be sorted case insensitive - tags.sort(key=lambda a: a.lower()) - categories.sort(key=lambda a: a.lower()) - if categories != ['']: - has_categories = True - else: - has_categories = False + tags = natsort.natsorted([tag for tag in self.site.posts_per_tag.keys() + if len(self.site.posts_per_tag[tag]) >= kw["taglist_minimum_post_count"]], + alg=natsort.ns.F | natsort.ns.IC) + categories = [cat.category_name for cat in self.site.category_hierarchy] + has_tags = (tags != []) and include_tags + has_categories = (categories != []) and include_categories template_name = "tags.tmpl" - kw['tags'] = tags - kw['categories'] = categories + kw = kw.copy() + if include_tags: + kw['tags'] = tags + if include_categories: + kw['categories'] = categories for lang in kw["translations"]: output_name = os.path.join( - kw['output_folder'], self.site.path('tag_index', None, lang)) + kw['output_folder'], self.site.path('tag_index' if has_tags else 'category_index', None, lang)) output_name = output_name context = {} - if has_categories: + if has_categories and has_tags: context["title"] = kw["messages"][lang]["Tags and Categories"] + elif has_categories: + context["title"] = kw["messages"][lang]["Categories"] else: context["title"] = kw["messages"][lang]["Tags"] - context["items"] = [(tag, self.site.link("tag", tag, lang)) for tag - in tags] + if has_tags: + context["items"] = [(tag, self.site.link("tag", tag, lang)) for tag + in tags] + else: + context["items"] = None if has_categories: context["cat_items"] = [(tag, self.site.link("category", tag, lang)) for tag in categories] + context['cat_hierarchy'] = [(node.name, node.category_name, node.category_path, + self.site.link("category", node.category_name), + node.indent_levels, node.indent_change_before, + node.indent_change_after) + for node in self.site.category_hierarchy] else: context["cat_items"] = None - context["permalink"] = self.site.link("tag_index", None, lang) + context["permalink"] = self.site.link("tag_index" if has_tags else "category_index", None, lang) context["description"] = context["title"] task = self.site.generic_post_list_renderer( lang, @@ -177,73 +227,66 @@ class RenderTags(Task): kw['filters'], context, ) - task_cfg = {1: task['uptodate'][0].config, 2: kw} - task['uptodate'] = [utils.config_changed(task_cfg)] + task['uptodate'] = task['uptodate'] + [utils.config_changed(kw, 'nikola.plugins.task.tags:page')] task['basename'] = str(self.name) yield task + def list_tags_page(self, kw): + """a global "all your tags/categories" page for each language""" + if self.site.config['TAG_PATH'] == self.site.config['CATEGORY_PATH']: + yield self._create_tags_page(kw, True, True) + else: + yield self._create_tags_page(kw, False, True) + yield self._create_tags_page(kw, True, False) + + def _get_title(self, tag, is_category): + if is_category: + return self.site.parse_category_name(tag)[-1] + else: + return tag + + def _get_description(self, tag, is_category, lang): + descriptions = self.site.config['CATEGORY_PAGES_DESCRIPTIONS'] if is_category else self.site.config['TAG_PAGES_DESCRIPTIONS'] + return descriptions[lang][tag] if lang in descriptions and tag in descriptions[lang] else None + + def _get_subcategories(self, category): + node = self.site.category_hierarchy_lookup[category] + return [(child.name, self.site.link("category", child.category_name)) for child in node.children] + def tag_page_as_index(self, tag, lang, post_list, kw, is_category): """render a sort of index page collection using only this tag's posts.""" kind = "category" if is_category else "tag" - def page_name(tagname, i, lang): - """Given tag, n, returns a page name.""" - name = self.site.path(kind, tag, lang) - if i: - name = name.replace('.html', '-{0}.html'.format(i)) - return name - - # FIXME: deduplicate this with render_indexes + def page_link(i, displayed_i, num_pages, force_addition, extension=None): + feed = "_atom" if extension == ".atom" else "" + return utils.adjust_name_for_index_link(self.site.link(kind + feed, tag, lang), i, displayed_i, lang, self.site, force_addition, extension) + + def page_path(i, displayed_i, num_pages, force_addition, extension=None): + feed = "_atom" if extension == ".atom" else "" + return utils.adjust_name_for_index_path(self.site.path(kind + feed, tag, lang), i, displayed_i, lang, self.site, force_addition, extension) + + context_source = {} + title = self._get_title(tag, is_category) + if kw["generate_rss"]: + # On a tag page, the feeds include the tag's feeds + rss_link = ("""<link rel="alternate" type="application/rss+xml" """ + """type="application/rss+xml" title="RSS for tag """ + """{0} ({1})" href="{2}">""".format( + title, lang, self.site.link(kind + "_rss", tag, lang))) + context_source['rss_link'] = rss_link + if is_category: + context_source["category"] = tag + context_source["category_path"] = self.site.parse_category_name(tag) + context_source["tag"] = title + indexes_title = kw["messages"][lang]["Posts about %s"] % title + context_source["description"] = self._get_description(tag, is_category, lang) + if is_category: + context_source["subcategories"] = self._get_subcategories(tag) template_name = "tagindex.tmpl" - # Split in smaller lists - lists = [] - while post_list: - lists.append(post_list[:kw["index_display_post_count"]]) - post_list = post_list[kw["index_display_post_count"]:] - num_pages = len(lists) - for i, post_list in enumerate(lists): - context = {} - if kw["generate_rss"]: - # On a tag page, the feeds include the tag's feeds - rss_link = ("""<link rel="alternate" type="application/rss+xml" """ - """type="application/rss+xml" title="RSS for tag """ - """{0} ({1})" href="{2}">""".format( - tag, lang, self.site.link(kind + "_rss", tag, lang))) - context['rss_link'] = rss_link - output_name = os.path.join(kw['output_folder'], - page_name(tag, i, lang)) - context["title"] = kw["messages"][lang][ - "Posts about %s"] % tag - context["prevlink"] = None - context["nextlink"] = None - context['index_teasers'] = kw['index_teasers'] - if i > 1: - context["prevlink"] = os.path.basename( - page_name(tag, i - 1, lang)) - if i == 1: - context["prevlink"] = os.path.basename( - page_name(tag, 0, lang)) - if i < num_pages - 1: - context["nextlink"] = os.path.basename( - page_name(tag, i + 1, lang)) - context["permalink"] = self.site.link(kind, tag, lang) - context["tag"] = tag - context["description"] = context["title"] - task = self.site.generic_post_list_renderer( - lang, - post_list, - output_name, - template_name, - kw['filters'], - context, - ) - task_cfg = {1: task['uptodate'][0].config, 2: kw} - task['uptodate'] = [utils.config_changed(task_cfg)] - task['basename'] = str(self.name) - yield task + yield self.site.generic_index_renderer(lang, post_list, indexes_title, template_name, context_source, kw, str(self.name), page_link, page_path) def tag_page_as_list(self, tag, lang, post_list, kw, is_category): """We render a single flat link list with this tag's posts""" @@ -253,12 +296,18 @@ class RenderTags(Task): kind, tag, lang)) context = {} context["lang"] = lang - context["title"] = kw["messages"][lang]["Posts about %s"] % tag + title = self._get_title(tag, is_category) + if is_category: + context["category"] = tag + context["category_path"] = self.site.parse_category_name(tag) + context["tag"] = title + context["title"] = kw["messages"][lang]["Posts about %s"] % title context["posts"] = post_list context["permalink"] = self.site.link(kind, tag, lang) - context["tag"] = tag context["kind"] = kind - context["description"] = context["title"] + context["description"] = self._get_description(tag, is_category, lang) + if is_category: + context["subcategories"] = self._get_subcategories(tag) task = self.site.generic_post_list_renderer( lang, post_list, @@ -267,8 +316,7 @@ class RenderTags(Task): kw['filters'], context, ) - task_cfg = {1: task['uptodate'][0].config, 2: kw} - task['uptodate'] = [utils.config_changed(task_cfg)] + task['uptodate'] = task['uptodate'] + [utils.config_changed(kw, 'nikola.plugins.task.tags:list')] task['basename'] = str(self.name) yield task @@ -281,26 +329,29 @@ class RenderTags(Task): self.site.path(kind + "_rss", tag, lang))) feed_url = urljoin(self.site.config['BASE_URL'], self.site.link(kind + "_rss", tag, lang).lstrip('/')) deps = [] + deps_uptodate = [] post_list = sorted(posts, key=lambda a: a.date) post_list.reverse() for post in post_list: deps += post.deps(lang) - return { + deps_uptodate += post.deps_uptodate(lang) + task = { 'basename': str(self.name), 'name': output_name, 'file_dep': deps, 'targets': [output_name], 'actions': [(utils.generic_rss_renderer, - (lang, "{0} ({1})".format(kw["blog_title"](lang), tag), + (lang, "{0} ({1})".format(kw["blog_title"](lang), self._get_title(tag, is_category)), kw["site_url"], None, post_list, output_name, kw["rss_teasers"], kw["rss_plain"], kw['feed_length'], - feed_url))], + feed_url, None, kw["rss_link_append_query"]))], 'clean': True, - 'uptodate': [utils.config_changed(kw)], + 'uptodate': [utils.config_changed(kw, 'nikola.plugins.task.tags:rss')] + deps_uptodate, 'task_dep': ['render_posts'], } + return utils.apply_filters(task, kw['filters']) - def slugify_name(self, name): + def slugify_tag_name(self, name): if self.site.config['SLUG_TAG_PATH']: name = utils.slugify(name) return name @@ -310,30 +361,64 @@ class RenderTags(Task): self.site.config['TAG_PATH'], self.site.config['INDEX_FILE']] if _f] + def category_index_path(self, name, lang): + return [_f for _f in [self.site.config['TRANSLATIONS'][lang], + self.site.config['CATEGORY_PATH'], + self.site.config['INDEX_FILE']] if _f] + def tag_path(self, name, lang): if self.site.config['PRETTY_URLS']: return [_f for _f in [ self.site.config['TRANSLATIONS'][lang], self.site.config['TAG_PATH'], - self.slugify_name(name), + self.slugify_tag_name(name), self.site.config['INDEX_FILE']] if _f] else: return [_f for _f in [ self.site.config['TRANSLATIONS'][lang], self.site.config['TAG_PATH'], - self.slugify_name(name) + ".html"] if _f] + self.slugify_tag_name(name) + ".html"] if _f] + + def tag_atom_path(self, name, lang): + return [_f for _f in [self.site.config['TRANSLATIONS'][lang], + self.site.config['TAG_PATH'], self.slugify_tag_name(name) + ".atom"] if + _f] def tag_rss_path(self, name, lang): return [_f for _f in [self.site.config['TRANSLATIONS'][lang], - self.site.config['TAG_PATH'], self.slugify_name(name) + ".xml"] if + self.site.config['TAG_PATH'], self.slugify_tag_name(name) + ".xml"] if _f] + def slugify_category_name(self, name): + path = self.site.parse_category_name(name) + if self.site.config['CATEGORY_OUTPUT_FLAT_HIERARCHY']: + path = path[-1:] # only the leaf + result = [self.slugify_tag_name(part) for part in path] + result[0] = self.site.config['CATEGORY_PREFIX'] + result[0] + if not self.site.config['PRETTY_URLS']: + result = ['-'.join(result)] + return result + + def _add_extension(self, path, extension): + path[-1] += extension + return path + def category_path(self, name, lang): + if self.site.config['PRETTY_URLS']: + return [_f for _f in [self.site.config['TRANSLATIONS'][lang], + self.site.config['CATEGORY_PATH']] if + _f] + self.slugify_category_name(name) + [self.site.config['INDEX_FILE']] + else: + return [_f for _f in [self.site.config['TRANSLATIONS'][lang], + self.site.config['CATEGORY_PATH']] if + _f] + self._add_extension(self.slugify_category_name(name), ".html") + + def category_atom_path(self, name, lang): return [_f for _f in [self.site.config['TRANSLATIONS'][lang], - self.site.config['TAG_PATH'], "cat_" + self.slugify_name(name) + ".html"] if - _f] + self.site.config['CATEGORY_PATH']] if + _f] + self._add_extension(self.slugify_category_name(name), ".atom") def category_rss_path(self, name, lang): return [_f for _f in [self.site.config['TRANSLATIONS'][lang], - self.site.config['TAG_PATH'], "cat_" + self.slugify_name(name) + ".xml"] if - _f] + self.site.config['CATEGORY_PATH']] if + _f] + self._add_extension(self.slugify_category_name(name), ".xml") diff --git a/nikola/plugins/template/__init__.py b/nikola/plugins/template/__init__.py index 6ad8bac..a1d17a6 100644 --- a/nikola/plugins/template/__init__.py +++ b/nikola/plugins/template/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated diff --git a/nikola/plugins/template/jinja.plugin b/nikola/plugins/template/jinja.plugin index 53b0fec..0bdcb94 100644 --- a/nikola/plugins/template/jinja.plugin +++ b/nikola/plugins/template/jinja.plugin @@ -4,6 +4,6 @@ Module = jinja [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Support for Jinja2 templates. diff --git a/nikola/plugins/template/jinja.py b/nikola/plugins/template/jinja.py index 5156f38..82e8397 100644 --- a/nikola/plugins/template/jinja.py +++ b/nikola/plugins/template/jinja.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -114,8 +114,7 @@ class JinjaTemplates(TemplateSystem): ast = self.lookup.parse(source) dep_names = meta.find_referenced_templates(ast) for dep_name in dep_names: - if (dep_name not in visited_templates - and dep_name is not None): + if (dep_name not in visited_templates and dep_name is not None): visited_templates.add(dep_name) queue.append(dep_name) self.dependency_cache[template_name] = deps diff --git a/nikola/plugins/template/mako.plugin b/nikola/plugins/template/mako.plugin index 71f2c71..2fe6d98 100644 --- a/nikola/plugins/template/mako.plugin +++ b/nikola/plugins/template/mako.plugin @@ -4,6 +4,6 @@ Module = mako [Documentation] Author = Roberto Alsina -Version = 0.1 +Version = 1.0 Website = http://getnikola.com Description = Support for Mako templates. diff --git a/nikola/plugins/template/mako.py b/nikola/plugins/template/mako.py index b9d856e..e5545f6 100644 --- a/nikola/plugins/template/mako.py +++ b/nikola/plugins/template/mako.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -115,7 +115,7 @@ class MakoTemplates(TemplateSystem): def render_template_to_string(self, template, context): """ Render template to a string using context. """ - context = context.update(self.filters) + context.update(self.filters) return Template(template).render(**context) diff --git a/nikola/post.py b/nikola/post.py index 350014a..466d5e0 100644 --- a/nikola/post.py +++ b/nikola/post.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -29,6 +29,8 @@ from __future__ import unicode_literals, print_function, absolute_import import io from collections import defaultdict import datetime +import hashlib +import json import os import re import string @@ -37,6 +39,8 @@ try: except ImportError: from urllib.parse import urljoin # NOQA +from . import utils + import dateutil.tz import lxml.html import natsort @@ -67,6 +71,7 @@ from .rc4 import rc4 __all__ = ['Post'] TEASER_REGEXP = re.compile('<!--\s*TEASER_END(:(.+))?\s*-->', re.IGNORECASE) +_UPGRADE_METADATA_ADVERTISED = False class Post(object): @@ -122,13 +127,18 @@ class Post(object): self.skip_untranslated = not self.config['SHOW_UNTRANSLATED_POSTS'] self._template_name = template_name self.is_two_file = True + self.newstylemeta = True self.hyphenate = self.config['HYPHENATE'] self._reading_time = None self._remaining_reading_time = None self._paragraph_count = None self._remaining_paragraph_count = None + self._dependency_file_fragment = defaultdict(list) + self._dependency_file_page = defaultdict(list) + self._dependency_uptodate_fragment = defaultdict(list) + self._dependency_uptodate_page = defaultdict(list) - default_metadata = get_meta(self, self.config['FILE_METADATA_REGEXP'], self.config['UNSLUGIFY_TITLES']) + default_metadata, self.newstylemeta = get_meta(self, self.config['FILE_METADATA_REGEXP'], self.config['UNSLUGIFY_TITLES']) self.meta = Functionary(lambda: None, self.default_lang) self.meta[self.default_lang] = default_metadata @@ -140,7 +150,9 @@ class Post(object): if lang != self.default_lang: meta = defaultdict(lambda: '') meta.update(default_metadata) - meta.update(get_meta(self, self.config['FILE_METADATA_REGEXP'], self.config['UNSLUGIFY_TITLES'], lang)) + _meta, _nsm = get_meta(self, self.config['FILE_METADATA_REGEXP'], self.config['UNSLUGIFY_TITLES'], lang) + self.newstylemeta = self.newstylemeta and _nsm + meta.update(_meta) self.meta[lang] = meta if not self.is_translation_available(self.default_lang): @@ -157,6 +169,14 @@ class Post(object): default_metadata['date'] = datetime.datetime.utcfromtimestamp( os.stat(self.source_path).st_ctime).replace(tzinfo=dateutil.tz.tzutc()).astimezone(tzinfo) + # If time zone is set, build localized datetime. + self.date = to_datetime(self.meta[self.default_lang]['date'], tzinfo) + + if 'updated' not in default_metadata: + default_metadata['updated'] = default_metadata.get('date', None) + + self.updated = to_datetime(default_metadata['updated']) + if 'title' not in default_metadata or 'slug' not in default_metadata \ or 'date' not in default_metadata: raise OSError("You must set a title (found '{0}'), a slug (found " @@ -170,9 +190,6 @@ class Post(object): # default value is 'text' default_metadata['type'] = 'text' - # If time zone is set, build localized datetime. - self.date = to_datetime(self.meta[self.default_lang]['date'], tzinfo) - self.publish_later = False if self.current_time is None else self.date >= self.current_time is_draft = False @@ -180,9 +197,10 @@ class Post(object): self._tags = {} for lang in self.translated_to: self._tags[lang] = natsort.natsorted( - list(set([x.strip() for x in self.meta[lang]['tags'].split(',')]))) + list(set([x.strip() for x in self.meta[lang]['tags'].split(',')])), + alg=natsort.ns.F | natsort.ns.IC) self._tags[lang] = [t for t in self._tags[lang] if t] - if 'draft' in self._tags[lang]: + if 'draft' in [_.lower() for _ in self._tags[lang]]: is_draft = True LOGGER.debug('The post "{0}" is a draft.'.format(self.source_path)) self._tags[lang].remove('draft') @@ -206,11 +224,26 @@ class Post(object): self.use_in_feeds = use_in_feeds and not is_draft and not is_private \ and not self.publish_later - # If mathjax is a tag, then enable mathjax rendering support - self.is_mathjax = 'mathjax' in self.tags + # If mathjax is a tag, or it's a ipynb post, then enable mathjax rendering support + self.is_mathjax = ('mathjax' in self.tags) or (self.compiler.name == 'ipynb') + + # Register potential extra dependencies + self.compiler.register_extra_dependencies(self) def __repr__(self): - return '<Post: {0}>'.format(self.source_path) + # Calculate a hash that represents most data about the post + m = hashlib.md5() + # source_path modification date (to avoid reading it) + m.update(utils.unicode_str(os.stat(self.source_path).st_mtime).encode('utf-8')) + clean_meta = {} + for k, v in self.meta.items(): + sub_meta = {} + clean_meta[k] = sub_meta + for kk, vv in v.items(): + if vv: + sub_meta[kk] = vv + m.update(utils.unicode_str(json.dumps(clean_meta, cls=utils.CustomEncoder, sort_keys=True)).encode('utf-8')) + return '<Post: {0!r} {1}>'.format(self.source_path, m.hexdigest()) def _has_pretty_url(self, lang): if self.pretty_urls and \ @@ -274,14 +307,20 @@ class Post(object): def template_name(self): return self.meta('template') or self._template_name - def formatted_date(self, date_format): + def formatted_date(self, date_format, date=None): """Return the formatted date, as unicode.""" - fmt_date = self.date.strftime(date_format) + if date: + fmt_date = date.strftime(date_format) + else: + fmt_date = self.date.strftime(date_format) # Issue #383, this changes from py2 to py3 if isinstance(fmt_date, bytes_str): fmt_date = fmt_date.decode('utf8') return fmt_date + def formatted_updated(self, date_format): + return self.formatted_date(date_format, self.updated) + def title(self, lang=None): """Return localized title. @@ -313,8 +352,76 @@ class Post(object): lang = nikola.utils.LocaleBorg().current_lang return self.meta[lang]['description'] + def add_dependency(self, dependency, add='both', lang=None): + """Adds a file dependency for tasks using that post. + + The ``dependency`` should be a string specifying a path, or a callable + which returns such a string or a list of strings. + + The ``add`` parameter can be 'both', 'fragment' or 'page', to indicate + that this dependency shall be used + * when rendering the fragment to HTML ('fragment' and 'both'), or + * when creating a page with parts of the ``Post`` embedded, which + includes the HTML resulting from compiling the fragment ('page' or + 'both'). + + If ``lang`` is not specified, this dependency is added for all languages.""" + if add not in {'fragment', 'page', 'both'}: + raise Exception("Add parameter is '{0}', but must be either 'fragment', 'page', or 'both'.".format(add)) + if add == 'fragment' or add == 'both': + self._dependency_file_fragment[lang].append((type(dependency) != str, dependency)) + if add == 'page' or add == 'both': + self._dependency_file_page[lang].append((type(dependency) != str, dependency)) + + def add_dependency_uptodate(self, dependency, is_callable=False, add='both', lang=None): + """Adds a dependency for task's ``uptodate`` for tasks using that post. + + This can be for example an ``utils.config_changed`` object, or a list of + such objects. + + The ``is_callable`` parameter specifies whether ``dependency`` is a + callable which generates an entry or a list of entries for the ``uptodate`` + list, or whether it is an entry which can directly be added (as a single + object or a list of objects). + + The ``add`` parameter can be 'both', 'fragment' or 'page', to indicate + that this dependency shall be used + * when rendering the fragment to HTML ('fragment' and 'both'), or + * when creating a page with parts of the ``Post`` embedded, which + includes the HTML resulting from compiling the fragment ('page' or + 'both'). + + If ``lang`` is not specified, this dependency is added for all languages. + + Example: + + post.add_dependency_uptodate( + utils.config_changed({1: some_data}, 'uniqueid'), False, 'page') + + """ + if add == 'fragment' or add == 'both': + self._dependency_uptodate_fragment[lang].append((is_callable, dependency)) + if add == 'page' or add == 'both': + self._dependency_uptodate_page[lang].append((is_callable, dependency)) + + def _get_dependencies(self, deps_list): + deps = [] + for dep in deps_list: + if dep[0]: + # callable + result = dep[1]() + else: + # can add directly + result = dep[1] + # if result is a list, add its contents + if type(result) == list: + deps.extend(result) + else: + deps.append(result) + return deps + def deps(self, lang): - """Return a list of dependencies to build this post's page.""" + """Return a list of file dependencies to build this post's page.""" deps = [] if self.default_lang in self.translated_to: deps.append(self.base_path) @@ -324,6 +431,19 @@ class Post(object): cand_2 = get_translation_candidate(self.config, self.base_path, lang) if os.path.exists(cand_1): deps.extend([cand_1, cand_2]) + deps += self._get_dependencies(self._dependency_file_page[lang]) + deps += self._get_dependencies(self._dependency_file_page[None]) + return deps + + def deps_uptodate(self, lang): + """Return a list of uptodate dependencies to build this post's page. + + These dependencies should be included in ``uptodate`` for the task + which generates the page.""" + deps = [] + deps += self._get_dependencies(self._dependency_uptodate_page[lang]) + deps += self._get_dependencies(self._dependency_uptodate_page[None]) + deps.append(utils.config_changed({1: sorted(self.compiler.config_dependencies)}, 'nikola.post.Post.deps_uptodate:compiler:' + self.source_path)) return deps def compile(self, lang): @@ -347,34 +467,41 @@ class Post(object): dest, self.is_two_file), if self.meta('password'): + # TODO: get rid of this feature one day (v8?; warning added in v7.3.0.) + LOGGER.warn("The post {0} is using the `password` attribute, which may stop working in the future.") + LOGGER.warn("Please consider switching to a more secure method of encryption.") + LOGGER.warn("More details: https://github.com/getnikola/nikola/issues/1547") wrap_encrypt(dest, self.meta('password')) if self.publish_later: LOGGER.notice('{0} is scheduled to be published in the future ({1})'.format( self.source_path, self.date)) - def extra_deps(self): - """get extra depepencies from .dep files - This file is created by ReST - """ - dep_path = self.base_path + '.dep' - if os.path.isfile(dep_path): - with io.open(dep_path, 'r+', encoding='utf8') as depf: - return [l.strip() for l in depf.readlines()] - return [] - def fragment_deps(self, lang): - """Return a list of dependencies to build this post's fragment.""" + """Return a list of uptodate dependencies to build this post's fragment. + + These dependencies should be included in ``uptodate`` for the task + which generates the fragment.""" deps = [] if self.default_lang in self.translated_to: deps.append(self.source_path) if os.path.isfile(self.metadata_path): deps.append(self.metadata_path) - deps.extend(self.extra_deps()) lang_deps = [] if lang != self.default_lang: lang_deps = [get_translation_candidate(self.config, d, lang) for d in deps] deps += lang_deps - return [d for d in deps if os.path.exists(d)] + deps = [d for d in deps if os.path.exists(d)] + deps += self._get_dependencies(self._dependency_file_fragment[lang]) + deps += self._get_dependencies(self._dependency_file_fragment[None]) + return deps + + def fragment_deps_uptodate(self, lang): + """Return a list of file dependencies to build this post's fragment.""" + deps = [] + deps += self._get_dependencies(self._dependency_uptodate_fragment[lang]) + deps += self._get_dependencies(self._dependency_uptodate_fragment[None]) + deps.append(utils.config_changed({1: sorted(self.compiler.config_dependencies)}, 'nikola.post.Post.deps_uptodate:compiler:' + self.source_path)) + return deps def is_translation_available(self, lang): """Return true if the translation actually exists.""" @@ -408,7 +535,8 @@ class Post(object): else: return get_translation_candidate(self.config, self.base_path, sorted(self.translated_to)[0]) - def text(self, lang=None, teaser_only=False, strip_html=False, show_read_more_link=True, rss_read_more_link=False): + def text(self, lang=None, teaser_only=False, strip_html=False, show_read_more_link=True, + rss_read_more_link=False, rss_links_append_query=None): """Read the post file for that language and return its contents. teaser_only=True breaks at the teaser marker and returns only the teaser. @@ -424,8 +552,16 @@ class Post(object): if lang is None: lang = nikola.utils.LocaleBorg().current_lang file_name = self._translated_file_path(lang) + + # Yes, we compile it and screw it. + # This may be controversial, but the user (or someone) is asking for the post text + # and the post should not just refuse to give it. + if not os.path.isfile(file_name): + self.compile(lang) + with io.open(file_name, "r", encoding="utf8") as post_file: data = post_file.read().strip() + if self.compiler.extension() == '.php': return data try: @@ -458,7 +594,7 @@ class Post(object): else: l = self.config['RSS_READ_MORE_LINK'](lang) if rss_read_more_link else self.config['INDEX_READ_MORE_LINK'](lang) teaser += l.format( - link=self.permalink(lang), + link=self.permalink(lang, query=rss_links_append_query), read_more=self.messages[lang]["Read more"], min_remaining_read=self.messages[lang]["%d min remaining to read"] % (self.remaining_reading_time), reading_time=self.reading_time, @@ -498,7 +634,12 @@ class Post(object): text = self.text(strip_html=True) words_per_minute = 220 words = len(text.split()) - self._reading_time = int(ceil(words / words_per_minute)) or 1 + markup = lxml.html.fromstring(self.text(strip_html=False)) + embeddables = [".//img", ".//picture", ".//video", ".//audio", ".//object", ".//iframe"] + media_time = 0 + for embedded in embeddables: + media_time += (len(markup.findall(embedded)) * 0.33) # +20 seconds + self._reading_time = int(ceil((words / words_per_minute) + media_time)) or 1 return self._reading_time @property @@ -574,9 +715,11 @@ class Post(object): self.folder, self.meta[lang]['slug'] + extension) if sep != os.sep: path = path.replace(os.sep, sep) + if path.startswith('./'): + path = path[2:] return path - def permalink(self, lang=None, absolute=False, extension='.html'): + def permalink(self, lang=None, absolute=False, extension='.html', query=None): if lang is None: lang = nikola.utils.LocaleBorg().current_lang @@ -596,9 +739,24 @@ class Post(object): link = urljoin(self.base_url, link[1:]) index_len = len(self.index_file) if self.strip_indexes and link[-(1 + index_len):] == '/' + self.index_file: - return link[:-index_len] - else: - return link + link = link[:-index_len] + if query: + link = link + "?" + query + return link + + @property + def previewimage(self, lang=None): + if lang is None: + lang = nikola.utils.LocaleBorg().current_lang + + image_path = self.meta[lang]['previewimage'] + + if not image_path: + return None + + # This is further parsed by the template, because we don’t have access + # to the URL replacer here. (Issue #1473) + return image_path def source_ext(self, prefix=False): """ @@ -679,6 +837,8 @@ def _get_metadata_from_file(meta_data): >>> g = _get_metadata_from_file >>> list(g([]).values()) [] + >>> str(g(["======","FooBar","======"])["title"]) + 'FooBar' >>> str(g(["FooBar","======"])["title"]) 'FooBar' >>> str(g(["#FooBar"])["title"]) @@ -714,6 +874,10 @@ def _get_metadata_from_file(meta_data): if re_rst_title.findall(line) and i > 0: meta['title'] = meta_data[i - 1].strip() if 'title' not in meta: + if (re_rst_title.findall(line) and i >= 0 and + re_rst_title.findall(meta_data[i + 2])): + meta['title'] = meta_data[i + 1].strip() + if 'title' not in meta: if re_md_title.findall(line): meta['title'] = re_md_title.findall(line)[0] @@ -726,6 +890,7 @@ def _get_metadata_from_file(meta_data): def get_metadata_from_meta_file(path, config=None, lang=None): """Takes a post path, and gets data from a matching .meta file.""" + global _UPGRADE_METADATA_ADVERTISED meta_path = os.path.splitext(path)[0] + '.meta' if lang and config: meta_path = get_translation_candidate(config, meta_path, lang) @@ -746,8 +911,12 @@ def get_metadata_from_meta_file(path, config=None, lang=None): if newstylemeta: # New-style metadata is basically the same as reading metadata from # a 1-file post. - return get_metadata_from_file(path, config, lang) + return get_metadata_from_file(path, config, lang), newstylemeta else: + if not _UPGRADE_METADATA_ADVERTISED: + LOGGER.warn("Some posts on your site have old-style metadata. You should upgrade them to the new format, with support for extra fields.") + LOGGER.warn("Install the 'upgrade_metadata' plugin (with 'nikola plugin -i upgrade_metadata') and run 'nikola upgrade_metadata'.") + _UPGRADE_METADATA_ADVERTISED = True while len(meta_data) < 7: meta_data.append("") (title, slug, date, tags, link, description, _type) = [ @@ -770,7 +939,7 @@ def get_metadata_from_meta_file(path, config=None, lang=None): if _type: meta['type'] = _type - return meta + return meta, newstylemeta elif lang: # Metadata file doesn't exist, but not default language, @@ -778,7 +947,7 @@ def get_metadata_from_meta_file(path, config=None, lang=None): # This makes the 2-file format detection more reliable (Issue #525) return get_metadata_from_meta_file(path, config, lang=None) else: - return {} + return {}, True def get_meta(post, file_metadata_regexp=None, unslugify_titles=False, lang=None): @@ -797,18 +966,24 @@ def get_meta(post, file_metadata_regexp=None, unslugify_titles=False, lang=None) except AttributeError: config = None - meta.update(get_metadata_from_meta_file(post.metadata_path, config, lang)) + _, newstylemeta = get_metadata_from_meta_file(post.metadata_path, config, lang) + meta.update(_) - if meta: - return meta - post.is_two_file = False + if not meta: + post.is_two_file = False if file_metadata_regexp is not None: meta.update(_get_metadata_from_filename_by_regex(post.source_path, file_metadata_regexp, unslugify_titles)) - meta.update(get_metadata_from_file(post.source_path, config, lang)) + if getattr(post, 'compiler', None): + compiler_meta = post.compiler.read_metadata(post, file_metadata_regexp, unslugify_titles, lang) + meta.update(compiler_meta) + + if not post.is_two_file: + # Meta file has precedence over file, which can contain garbage. + meta.update(get_metadata_from_file(post.source_path, config, lang)) if lang is None: # Only perform these checks for the default language @@ -823,15 +998,33 @@ def get_meta(post, file_metadata_regexp=None, unslugify_titles=False, lang=None) meta['title'] = os.path.splitext( os.path.basename(post.source_path))[0] - return meta + return meta, newstylemeta -def hyphenate(dom, lang): - if pyphen is not None: - hyphenator = pyphen.Pyphen(lang=lang) +def hyphenate(dom, _lang): + # circular import prevention + from .nikola import LEGAL_VALUES + lang = LEGAL_VALUES['PYPHEN_LOCALES'].get(_lang, pyphen.language_fallback(_lang)) + if pyphen is not None and lang is not None: + # If pyphen does exist, we tell the user when configuring the site. + # If it does not support a language, we ignore it quietly. + try: + hyphenator = pyphen.Pyphen(lang=lang) + except KeyError: + LOGGER.error("Cannot find hyphenation dictoniaries for {0} (from {1}).".format(lang, _lang)) + LOGGER.error("Pyphen cannot be installed to ~/.local (pip install --user).") for tag in ('p', 'li', 'span'): for node in dom.xpath("//%s[not(parent::pre)]" % tag): - insert_hyphens(node, hyphenator) + skip_node = False + skippable_nodes = ['kbd', 'code', 'samp', 'mark', 'math', 'data', 'ruby', 'svg'] + if node.getchildren(): + for child in node.getchildren(): + if child.tag in skippable_nodes or (child.tag == 'span' and 'math' in child.get('class', [])): + skip_node = True + elif 'math' in node.get('class', []): + skip_node = True + if not skip_node: + insert_hyphens(node, hyphenator) return dom diff --git a/nikola/utils.py b/nikola/utils.py index 87826ff..3708775 100644 --- a/nikola/utils.py +++ b/nikola/utils.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -27,32 +27,66 @@ """Utility functions.""" from __future__ import print_function, unicode_literals, absolute_import -from collections import defaultdict, Callable import calendar import datetime import dateutil.tz import hashlib +import io import locale import logging +import natsort import os import re import json import shutil import subprocess import sys -from zipfile import ZipFile as zipf -try: - from imp import reload -except ImportError: - pass - import dateutil.parser import dateutil.tz import logbook +import warnings +import PyRSS2Gen as rss +from collections import defaultdict, Callable from logbook.more import ExceptionHandler, ColorizedStderrHandler +from pygments.formatters import HtmlFormatter +from zipfile import ZipFile as zipf +from doit import tools +from unidecode import unidecode +from pkg_resources import resource_filename +from doit.cmdparse import CmdParse from nikola import DEBUG +__all__ = ['CustomEncoder', 'get_theme_path', 'get_theme_chain', 'load_messages', 'copy_tree', + 'copy_file', 'slugify', 'unslugify', 'to_datetime', 'apply_filters', + 'config_changed', 'get_crumbs', 'get_tzname', 'get_asset_path', + '_reload', 'unicode_str', 'bytes_str', 'unichr', 'Functionary', + 'TranslatableSetting', 'TemplateHookRegistry', 'LocaleBorg', + 'sys_encode', 'sys_decode', 'makedirs', 'get_parent_theme_name', + 'demote_headers', 'get_translation_candidate', 'write_metadata', + 'ask', 'ask_yesno', 'options2docstring', 'os_path_split', + 'get_displayed_page_number', 'adjust_name_for_index_path_list', + 'adjust_name_for_index_path', 'adjust_name_for_index_link', + 'NikolaPygmentsHTML', 'create_redirect', 'TreeNode', + 'flatten_tree_structure', 'parse_escaped_hierarchical_category_name', + 'join_hierarchical_category_path', 'indent'] + +# Are you looking for 'generic_rss_renderer'? +# It's defined in nikola.nikola.Nikola (the site object). + +if sys.version_info[0] == 3: + # Python 3 + bytes_str = bytes + unicode_str = str + unichr = chr + raw_input = input + from imp import reload as _reload +else: + bytes_str = str + unicode_str = unicode # NOQA + _reload = reload # NOQA + unichr = unichr + class ApplicationWarning(Exception): pass @@ -72,9 +106,9 @@ def get_logger(name, handlers): l = logbook.Logger(name) for h in handlers: if isinstance(h, list): - l.handlers = h + l.handlers += h else: - l.handlers = [h] + l.handlers.append(h) return l @@ -97,9 +131,6 @@ else: logging.basicConfig(level=logging.INFO) -import warnings - - def showwarning(message, category, filename, lineno, file=None, line=None): """Show a warning (from the warnings subsystem) to the user.""" try: @@ -156,39 +187,8 @@ def req_missing(names, purpose, python=True, optional=False): return msg -if sys.version_info[0] == 3: - # Python 3 - bytes_str = bytes - unicode_str = str - unichr = chr - raw_input = input - from imp import reload as _reload -else: - bytes_str = str - unicode_str = unicode # NOQA - _reload = reload # NOQA - unichr = unichr - -from doit import tools -from unidecode import unidecode -from pkg_resources import resource_filename -from nikola import filters as task_filters - -import PyRSS2Gen as rss - -__all__ = ['get_theme_path', 'get_theme_chain', 'load_messages', 'copy_tree', - 'copy_file', 'slugify', 'unslugify', 'to_datetime', 'apply_filters', - 'config_changed', 'get_crumbs', 'get_tzname', 'get_asset_path', - '_reload', 'unicode_str', 'bytes_str', 'unichr', 'Functionary', - 'TranslatableSetting', 'TemplateHookRegistry', 'LocaleBorg', - 'sys_encode', 'sys_decode', 'makedirs', 'get_parent_theme_name', - 'demote_headers', 'get_translation_candidate', 'write_metadata', - 'ask', 'ask_yesno'] - -# Are you looking for 'generic_rss_renderer'? -# It's defined in nikola.nikola.Nikola (the site object). - +from nikola import filters as task_filters # NOQA ENCODING = sys.getfilesystemencoding() or sys.stdin.encoding @@ -208,11 +208,20 @@ def sys_decode(thing): def makedirs(path): """Create a folder.""" - if not path or os.path.isdir(path): + if not path: return if os.path.exists(path): - raise OSError('Path {0} already exists and is not a folder.') - os.makedirs(path) + if not os.path.isdir(path): + raise OSError('Path {0} already exists and is not a folder.'.format(path)) + else: + return + try: + os.makedirs(path) + return + except Exception: + if os.path.isdir(path): + return + raise class Functionary(defaultdict): @@ -368,8 +377,10 @@ class TranslatableSetting(object): for a in f[0] + tuple(f[1].values()): if isinstance(a, dict): langkeys += list(a) + # Now that we know all this, we go through all the languages we have. allvalues = set(keys + langkeys + list(self.values)) + self.values['__orig__'] = self.values[self.default_lang] for l in allvalues: if l in keys: oargs, okwargs = formats[l] @@ -383,19 +394,22 @@ class TranslatableSetting(object): # We create temporary TranslatableSettings and replace the # values with them. if isinstance(a, dict): - a = TranslatableSetting('NULL', a) + a = TranslatableSetting('NULL', a, self.translations) args.append(a(l)) else: args.append(a) for k, v in okwargs.items(): if isinstance(v, dict): - v = TranslatableSetting('NULL', v) + v = TranslatableSetting('NULL', v, self.translations) kwargs.update({k: v(l)}) else: kwargs.update({k: v}) - self.values[l] = self.values[l].format(*args, **kwargs) + if l in self.values: + self.values[l] = self.values[l].format(*args, **kwargs) + else: + self.values[l] = self.values['__orig__'].format(*args, **kwargs) self.values.default_factory = lambda: self.values[self.default_lang] return self @@ -472,7 +486,7 @@ class TemplateHookRegistry(object): self._items.append((c, inp, wants_site_and_context, args, kwargs)) def __hash__(self): - return config_changed({self.name: self._items}) + return hash(config_changed({self.name: self._items})._calc_digest()) def __str__(self): return '<TemplateHookRegistry: {0}>'.format(self._items) @@ -490,6 +504,12 @@ class CustomEncoder(json.JSONEncoder): class config_changed(tools.config_changed): """ A copy of doit's but using pickle instead of serializing manually.""" + def __init__(self, config, identifier=None): + super(config_changed, self).__init__(config) + self.identifier = '_config_changed' + if identifier is not None: + self.identifier += ':' + identifier + def _calc_digest(self): if isinstance(self.config, str): return self.config @@ -507,6 +527,16 @@ class config_changed(tools.config_changed): '{0}, must be string or dict'.format(type( self.config))) + def configure_task(self, task): + task.value_savers.append(lambda: {self.identifier: self._calc_digest()}) + + def __call__(self, task, values): + """Return True if config values are unchanged.""" + last_success = values.get(self.identifier) + if last_success is None: + return False + return (last_success == self._calc_digest()) + def __repr__(self): return "Change with config: {0}".format(json.dumps(self.config, cls=CustomEncoder)) @@ -576,7 +606,7 @@ def load_messages(themes, translations, default_lang): and "younger" themes have priority. """ messages = Functionary(dict, default_lang) - oldpath = sys.path[:] + oldpath = list(sys.path) for theme_name in themes[::-1]: msg_folder = os.path.join(get_theme_path(theme_name), 'messages') default_folder = os.path.join(get_theme_path('base'), 'messages') @@ -587,7 +617,7 @@ def load_messages(themes, translations, default_lang): try: translation = __import__('messages_' + lang) # If we don't do the reload, the module is cached - reload(translation) + _reload(translation) if sorted(translation.MESSAGES.keys()) !=\ sorted(english.MESSAGES.keys()) and \ lang not in warned: @@ -877,7 +907,10 @@ def get_crumbs(path, is_file=False, index_folder=None): for i, crumb in enumerate(crumbs[::-1]): if folder[-1] == os.sep: folder = folder[:-1] - index_post = index_folder.parse_index(folder) + # We don't care about the created Post() object except for its title; + # hence, the input_folder and output_folder given to + # index_folder.parse_index() don't matter + index_post = index_folder.parse_index(folder, '', '') folder = folder.replace(crumb, '') if index_post: crumb = index_post.title() or crumb @@ -1038,6 +1071,25 @@ class LocaleBorg(object): return s +class ExtendedRSS2(rss.RSS2): + xsl_stylesheet_href = None + + def publish(self, handler): + if self.xsl_stylesheet_href: + handler.processingInstruction("xml-stylesheet", 'type="text/xsl" href="{0}" media="all"'.format(self.xsl_stylesheet_href)) + # old-style class in py2 + rss.RSS2.publish(self, handler) + + def publish_extensions(self, handler): + if self.self_url: + handler.startElement("atom:link", { + 'href': self.self_url, + 'rel': "self", + 'type': "application/rss+xml" + }) + handler.endElement("atom:link") + + class ExtendedItem(rss.RSSItem): def __init__(self, **kw): @@ -1096,8 +1148,13 @@ def get_root_dir(): """Find root directory of nikola installation by looking for conf.py""" root = os.getcwd() + if sys.version_info[0] == 2: + confname = b'conf.py' + else: + confname = 'conf.py' + while True: - if os.path.exists(os.path.join(root, 'conf.py')): + if os.path.exists(os.path.join(root, confname)): return root else: basedir = os.path.split(root)[0] @@ -1174,7 +1231,7 @@ def get_translation_candidate(config, path, lang): def write_metadata(data): """Write metadata.""" - order = ('title', 'slug', 'date', 'tags', 'link', 'description', 'type') + order = ('title', 'slug', 'date', 'tags', 'category', 'link', 'description', 'type') f = '.. {0}: {1}' meta = [] for k in order: @@ -1184,8 +1241,8 @@ def write_metadata(data): pass # Leftover metadata (user-specified/non-default). - for k, v in data.items(): - meta.append(f.format(k, v)) + for k in natsort.natsorted(list(data.keys()), alg=natsort.ns.F | natsort.ns.IC): + meta.append(f.format(k, data[k])) meta.append('') @@ -1198,7 +1255,10 @@ def ask(query, default=None): default_q = ' [{0}]'.format(default) else: default_q = '' - inp = raw_input("{query}{default_q}: ".format(query=query, default_q=default_q)).strip() + if sys.version_info[0] == 3: + inp = raw_input("{query}{default_q}: ".format(query=query, default_q=default_q)).strip() + else: + inp = raw_input("{query}{default_q}: ".format(query=query, default_q=default_q).encode('utf-8')).strip() if inp or default is None: return inp else: @@ -1213,7 +1273,10 @@ def ask_yesno(query, default=None): default_q = ' [Y/n]' elif default is False: default_q = ' [y/N]' - inp = raw_input("{query}{default_q} ".format(query=query, default_q=default_q)).strip() + if sys.version_info[0] == 3: + inp = raw_input("{query}{default_q} ".format(query=query, default_q=default_q)).strip() + else: + inp = raw_input("{query}{default_q} ".format(query=query, default_q=default_q).encode('utf-8')).strip() if inp: return inp.lower().startswith('y') elif default is not None: @@ -1223,10 +1286,6 @@ def ask_yesno(query, default=None): return ask_yesno(query, default) -from nikola.plugin_categories import Command -from doit.cmdparse import CmdParse - - class CommandWrapper(object): """Converts commands into functions.""" @@ -1253,32 +1312,58 @@ class Commands(object): >>> commands.check(list=True) # doctest: +SKIP """ - def __init__(self, main): + def __init__(self, main, config, doitargs): """Takes a main instance, works as wrapper for commands.""" self._cmdnames = [] - for k, v in main.get_commands().items(): - self._cmdnames.append(k) + self._main = main + self._config = config + self._doitargs = doitargs + try: + cmdict = self._doitargs['cmds'].to_dict() + except AttributeError: # not a doit PluginDict + cmdict = self._doitargs['cmds'] + for k, v in cmdict.items(): + # cleanup: run is doit-only, init is useless in an existing site if k in ['run', 'init']: continue if sys.version_info[0] == 2: k2 = bytes(k) else: k2 = k + + self._cmdnames.append(k) + + try: + # nikola command: already instantiated (singleton) + opt = v.get_options() + except TypeError: + # doit command: needs some help + opt = v(config=self._config, **self._doitargs).get_options() nc = type( k2, (CommandWrapper,), { - '__doc__': options2docstring(k, main.sub_cmds[k].options) + '__doc__': options2docstring(k, opt) }) setattr(self, k, nc(k, self)) - self.main = main def _run(self, cmd_args): - self.main.run(cmd_args) + self._main.run(cmd_args) def _run_with_kw(self, cmd, *a, **kw): - cmd = self.main.sub_cmds[cmd] - options, _ = CmdParse(cmd.options).parse([]) + # cyclic import hack + from nikola.plugin_categories import Command + try: + cmd = self._doitargs['cmds'].get_plugin(cmd) + except AttributeError: # not a doit PluginDict + cmd = self._doitargs['cmds'][cmd] + try: + opt = cmd.get_options() + except TypeError: + cmd = cmd(config=self._config, **self._doitargs) + opt = cmd.get_options() + + options, _ = CmdParse(opt).parse([]) options.update(kw) if isinstance(cmd, Command): cmd.execute(options=options, args=a) @@ -1305,3 +1390,249 @@ def options2docstring(name, options): for opt in options: result.append('{0} type {1} default {2}'.format(opt.name, opt.type.__name__, opt.default)) return '\n'.join(result) + + +class NikolaPygmentsHTML(HtmlFormatter): + """A Nikola-specific modification of Pygments’ HtmlFormatter.""" + def __init__(self, anchor_ref, classes=None, linenos='table', linenostart=1): + if classes is None: + classes = ['code', 'literal-block'] + self.nclasses = classes + super(NikolaPygmentsHTML, self).__init__( + cssclass='code', linenos=linenos, linenostart=linenostart, nowrap=False, + lineanchors=slugify(anchor_ref, force=True), anchorlinenos=True) + + def wrap(self, source, outfile): + """ + Wrap the ``source``, which is a generator yielding + individual lines, in custom generators. + """ + + style = [] + if self.prestyles: + style.append(self.prestyles) + if self.noclasses: + style.append('line-height: 125%') + style = '; '.join(style) + classes = ' '.join(self.nclasses) + + yield 0, ('<pre class="{0}"'.format(classes) + (style and ' style="{0}"'.format(style)) + '>') + for tup in source: + yield tup + yield 0, '</pre>' + + +def get_displayed_page_number(i, num_pages, site): + if not i: + i = 0 + if site.config["INDEXES_STATIC"]: + return i if i > 0 else num_pages + else: + return i + 1 if site.config["INDEXES_PAGES_MAIN"] else i + + +def adjust_name_for_index_path_list(path_list, i, displayed_i, lang, site, force_addition=False, extension=None): + index_file = site.config["INDEX_FILE"] + if i or force_addition: + path_list = list(path_list) + if force_addition and not i: + i = 0 + if not extension: + _, extension = os.path.splitext(index_file) + if len(path_list) > 0 and path_list[-1] == '': + path_list[-1] = index_file + elif len(path_list) == 0 or not path_list[-1].endswith(extension): + path_list.append(index_file) + if site.config["PRETTY_URLS"] and site.config["INDEXES_PRETTY_PAGE_URL"](lang) and path_list[-1] == index_file: + path_schema = site.config["INDEXES_PRETTY_PAGE_URL"](lang) + if isinstance(path_schema, (bytes_str, unicode_str)): + path_schema = [path_schema] + else: + path_schema = None + if path_schema is not None: + del path_list[-1] + for entry in path_schema: + path_list.append(entry.format(number=displayed_i, old_number=i, index_file=index_file)) + else: + path_list[-1] = '{0}-{1}{2}'.format(os.path.splitext(path_list[-1])[0], i, extension) + return path_list + + +def os_path_split(path): + result = [] + while True: + previous_path = path + path, tail = os.path.split(path) + if path == previous_path and tail == '': + result.insert(0, path) + break + result.insert(0, tail) + if len(path) == 0: + break + return result + + +def adjust_name_for_index_path(name, i, displayed_i, lang, site, force_addition=False, extension=None): + return os.path.join(*adjust_name_for_index_path_list(os_path_split(name), i, displayed_i, lang, site, force_addition, extension)) + + +def adjust_name_for_index_link(name, i, displayed_i, lang, site, force_addition=False, extension=None): + link = adjust_name_for_index_path_list(name.split('/'), i, displayed_i, lang, site, force_addition, extension) + if not extension == ".atom": + if len(link) > 0 and link[-1] == site.config["INDEX_FILE"] and site.config["STRIP_INDEXES"]: + link[-1] = '' + return '/'.join(link) + + +def create_redirect(src, dst): + makedirs(os.path.dirname(src)) + with io.open(src, "w+", encoding="utf8") as fd: + fd.write('<!DOCTYPE html>\n<head>\n<meta charset="utf-8">\n' + '<title>Redirecting...</title>\n<meta name="robots" ' + 'content="noindex">\n<meta http-equiv="refresh" content="0; ' + 'url={0}">\n</head>\n<body>\n<p>Page moved ' + '<a href="{0}">here</a>.</p>\n</body>'.format(dst)) + + +class TreeNode(object): + indent_levels = None # use for formatting comments as tree + indent_change_before = 0 # use for formatting comments as tree + indent_change_after = 0 # use for formatting comments as tree + + # The indent levels and changes allow to render a tree structure + # without keeping track of all that information during rendering. + # + # The indent_change_before is the different between the current + # comment's level and the previous comment's level; if the number + # is positive, the current level is indented further in, and if it + # is negative, it is indented further out. Positive values can be + # used to open HTML tags for each opened level. + # + # The indent_change_after is the difference between the next + # comment's level and the current comment's level. Negative values + # can be used to close HTML tags for each closed level. + # + # The indent_levels list contains one entry (index, count) per + # level, informing about the index of the current comment on that + # level and the count of comments on that level (before a comment + # of a higher level comes). This information can be used to render + # tree indicators, for example to generate a tree such as: + # + # +--- [(0,3)] + # +-+- [(1,3)] + # | +--- [(1,3), (0,2)] + # | +-+- [(1,3), (1,2)] + # | +--- [(1,3), (1,2), (0, 1)] + # +-+- [(2,3)] + # +- [(2,3), (0,1)] + # + # (The lists used as labels represent the content of the + # indent_levels property for that node.) + + def __init__(self, name, parent=None): + self.name = name + self.parent = parent + self.children = [] + + def get_path(self): + path = [] + curr = self + while curr is not None: + path.append(curr) + curr = curr.parent + return reversed(path) + + def get_children(self): + return self.children + + +def flatten_tree_structure(root_list): + elements = [] + + def generate(input_list, indent_levels_so_far): + for index, element in enumerate(input_list): + # add to destination + elements.append(element) + # compute and set indent levels + indent_levels = indent_levels_so_far + [(index, len(input_list))] + element.indent_levels = indent_levels + # add children + children = element.get_children() + element.children_count = len(children) + generate(children, indent_levels) + + generate(root_list, []) + # Add indent change counters + level = 0 + last_element = None + for element in elements: + new_level = len(element.indent_levels) + # Compute level change before this element + change = new_level - level + if last_element is not None: + last_element.indent_change_after = change + element.indent_change_before = change + # Update variables + level = new_level + last_element = element + # Set level change after last element + if last_element is not None: + last_element.indent_change_after = -level + return elements + + +def parse_escaped_hierarchical_category_name(category_name): + result = [] + current = None + index = 0 + next_backslash = category_name.find('\\', index) + next_slash = category_name.find('/', index) + while index < len(category_name): + if next_backslash == -1 and next_slash == -1: + current = (current if current else "") + category_name[index:] + index = len(category_name) + elif next_slash >= 0 and (next_backslash == -1 or next_backslash > next_slash): + result.append((current if current else "") + category_name[index:next_slash]) + current = '' + index = next_slash + 1 + next_slash = category_name.find('/', index) + else: + if len(category_name) == next_backslash + 1: + raise Exception("Unexpected '\\' in '{0}' at last position!".format(category_name)) + esc_ch = category_name[next_backslash + 1] + if esc_ch not in {'/', '\\'}: + raise Exception("Unknown escape sequence '\\{0}' in '{1}'!".format(esc_ch, category_name)) + current = (current if current else "") + category_name[index:next_backslash] + esc_ch + index = next_backslash + 2 + next_backslash = category_name.find('\\', index) + if esc_ch == '/': + next_slash = category_name.find('/', index) + if current is not None: + result.append(current) + return result + + +def join_hierarchical_category_path(category_path): + def escape(s): + return s.replace('\\', '\\\\').replace('/', '\\/') + + return '/'.join([escape(p) for p in category_path]) + + +# Stolen from textwrap in Python 3.4.3. +def indent(text, prefix, predicate=None): + """Adds 'prefix' to the beginning of selected lines in 'text'. + + If 'predicate' is provided, 'prefix' will only be added to the lines + where 'predicate(line)' is True. If 'predicate' is not provided, + it will default to adding 'prefix' to all non-empty lines that do not + consist solely of whitespace characters. + """ + if predicate is None: + def predicate(line): + return line.strip() + + def prefixed_lines(): + for line in text.splitlines(True): + yield (prefix + line if predicate(line) else line) + return ''.join(prefixed_lines()) diff --git a/nikola/winutils.py b/nikola/winutils.py index 712de39..8e29f5b 100644 --- a/nikola/winutils.py +++ b/nikola/winutils.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -# Copyright © 2012-2014 Roberto Alsina and others. +# Copyright © 2012-2015 Roberto Alsina and others. # Permission is hereby granted, free of charge, to any # person obtaining a copy of this software and associated @@ -29,6 +29,7 @@ from __future__ import print_function, unicode_literals import os import shutil +import io # don't add imports to nikola code, will be imported in setup.py @@ -63,9 +64,14 @@ def fix_all_git_symlinked(topdir): Weakness: if interrupted of fail amidst a directory copy, next run will not see the missing files. """ - with open(topdir + r'\nikola\data\symlinked.txt', 'rb') as f: - all_bytes = f.read() - text = all_bytes.decode('utf8') + # Determine whether or not symlinks need fixing (they don’t if installing + # from a .tar.gz file) + with io.open(topdir + r'\nikola\data\symlink-test-link.txt', 'r', encoding='utf-8') as f: + text = f.read() + if text.startswith("NIKOLA_SYMLINKS=OK"): + return -1 + with io.open(topdir + r'\nikola\data\symlinked.txt', 'r', encoding='utf-8') as f: + text = f.read() # expect each line a relpath from git or zip root, # smoke test relpaths are relative to git root if text.startswith('.'): @@ -86,7 +92,7 @@ def fix_all_git_symlinked(topdir): continue # build src path and do some basic validation - with open(os.path.join(topdir, dst), 'r') as f: + with io.open(os.path.join(topdir, dst), 'r', encoding='utf-8') as f: text = f.read() dst_dir = os.path.dirname(dst) try: diff --git a/requirements-extras.txt b/requirements-extras.txt index 846af71..56f3adb 100644 --- a/requirements-extras.txt +++ b/requirements-extras.txt @@ -1,12 +1,13 @@ -r requirements.txt -requests>=2.2.0 Markdown>=2.4.0 Jinja2>=2.7.2 -livereload==2.2.1 pyphen>=0.9.1 micawber>=0.3.0 -pygal>=1.4.6 +pygal==1.7.0 typogrify>=2.0.4 phpserialize>=1.3 webassets>=0.10.1 -ipython>=1.2.1 +ipython[notebook]>=2.0.0 +ghp-import>=0.4.1 +ws4py==0.3.4 +watchdog==0.8.3 diff --git a/requirements-tests.txt b/requirements-tests.txt index 17c04fb..ce6bf8a 100644 --- a/requirements-tests.txt +++ b/requirements-tests.txt @@ -1,7 +1,8 @@ -r requirements-extras.txt mock==1.0.1 coverage==3.7.1 -pytest==2.6.2 -pytest-cov==1.8.0 -freezegun==0.1.18 -python-coveralls==2.4.2 +pytest==2.7.2 +pytest-cov==1.8.1 +freezegun==0.3.4 +python-coveralls==2.5.0 +colorama==0.3.3 diff --git a/requirements.txt b/requirements.txt index bf930d2..2334e9c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,14 +1,15 @@ -doit>=0.23.0 +doit==0.28.0 Pygments>=1.6 Pillow>=2.4.0 -python-dateutil>=2.2 +python-dateutil==2.4.2 docutils>=0.12 mako>=1.0.0 unidecode>=0.04.16 lxml>=3.3.5 -yapsy>=1.10.423 +Yapsy==1.11.223 PyRSS2Gen>=1.1 logbook>=0.7.0 blinker>=1.3 setuptools>=5.4.1 -natsort>=3.3.0 +natsort>=3.5.2 +requests>=2.2.0 diff --git a/scripts/generate_conf.py b/scripts/generate_conf.py new file mode 100755 index 0000000..37a3a94 --- /dev/null +++ b/scripts/generate_conf.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python +# Generate a conf.py file from the template, using default settings. + +import nikola.plugins.command.init + +try: + print(nikola.plugins.command.init.CommandInit.create_configuration_to_string()) +except: + print(nikola.plugins.command.init.CommandInit.create_configuration_to_string().encode('utf-8')) diff --git a/scripts/getwheelhouse.sh b/scripts/getwheelhouse.sh index 911ffbd..753fc2b 100755 --- a/scripts/getwheelhouse.sh +++ b/scripts/getwheelhouse.sh @@ -3,5 +3,7 @@ for i in $@; do wget https://github.com/getnikola/wheelhouse/archive/v$i'.zip' unzip 'v'$i'.zip' pip install --use-wheel --no-index --find-links=wheelhouse-$i lxml Pillow ipython + # Install Markdown for Python 2.6. + pip install --use-wheel --no-index --find-links=wheelhouse-$i Markdown || true rm -rf wheelhouse-$i 'v'$i'.zip' done diff --git a/scripts/github-release.py b/scripts/github-release.py new file mode 100755 index 0000000..8280fda --- /dev/null +++ b/scripts/github-release.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python +import subprocess +import sys +import os + +if not os.path.exists('.pypt/gh-token'): + print("To use this script, you must create a GitHub token first.") + print("Get a token here: https://github.com/settings/tokens") + print("Then, put it in a file named .pypt/gh-token") + exit(1) + +inpf = input if sys.version_info[0] == 3 else raw_input + +FILE = inpf("Markdown file to use: ") +BASEDIR = os.getcwd() +REPO = 'getnikola/nikola' +TAG = inpf("Tag name (usually vX.Y.Z): ") + +subprocess.call(['.pypt/ghrel', FILE, BASEDIR, REPO, TAG]) diff --git a/scripts/jinjify.py b/scripts/jinjify.py index be69731..30f8029 100755 --- a/scripts/jinjify.py +++ b/scripts/jinjify.py @@ -22,6 +22,7 @@ dumb_replacements = [ ] dumber_replacements = [ + ['<%! import json %>\n\n', ''], ["<html\n\\", "<html\n"], ["\n'\\\n", "\n'\n"], ["{% endif %}\n\\", "{% endif %}\n"] @@ -76,15 +77,18 @@ def jinjify(in_theme, out_theme): if child in mappings: parent = mappings[child] - with open(os.path.join(out_theme, "parent"), "wb+") as outf: - outf.write(parent + '\n') + with io.open(os.path.join(out_theme, "parent"), "w+", encoding='utf-8') as outf: + outf.write(u'{0}\n'.format(parent)) - with open(os.path.join(out_theme, "engine"), "wb+") as outf: - outf.write("jinja\n") + with io.open(os.path.join(out_theme, "engine"), "w+", encoding='utf-8') as outf: + outf.write(u"jinja\n") - # Copy assets - # shutil.rmtree(os.path.join(out_theme, "assets")) - # shutil.copytree(os.path.join(in_theme, "assets"), os.path.join(out_theme, "assets")) + # Copy assets in bootstrap/bootstrap3 + if child in ('bootstrap-jinja', 'bootstrap3-jinja'): + shutil.rmtree(os.path.join(out_theme, "assets")) + shutil.copytree( + os.path.join(in_theme, "assets"), os.path.join(out_theme, "assets"), + symlinks=True) # Copy bundles # shutil.copy(os.path.join(in_theme, "bundles"), os.path.join(out_theme, "bundles")) diff --git a/scripts/set_version.py b/scripts/set_version.py index 6a64489..7e6c3e0 100755 --- a/scripts/set_version.py +++ b/scripts/set_version.py @@ -9,6 +9,8 @@ import os import re import sys import glob +import subprocess +import io def sed_like_thing(pattern, repl, path): @@ -30,8 +32,16 @@ if __name__ == "__main__": sed_like_thing(":Version: .*", ":Version: {0}".format(version), doc) sed_like_thing("version='.+'", "version='{0}'".format(version), 'setup.py') - sed_like_thing("version = '.+'", "version = '{0}'".format(version), os.path.join('docs', 'sphinx', 'conf.py')) - sed_like_thing("release = '.+'", "release = '{0}'".format(version), os.path.join('docs', 'sphinx', 'conf.py')) + sed_like_thing("version = .*", "version = '{0}'".format(version), os.path.join('docs', 'sphinx', 'conf.py')) + sed_like_thing("release = .*", "release = '{0}'".format(version), os.path.join('docs', 'sphinx', 'conf.py')) sed_like_thing('__version__ = ".*"', '__version__ = "{0}"'.format(version), os.path.join('nikola', '__init__.py')) sed_like_thing('New in master', 'New in v{0}'.format(version), 'CHANGES.txt') - os.system("help2man -h help -N --version-string='{0}' nikola > {1}".format(version, os.path.join('docs', 'man', 'nikola.1'))) + sed_like_thing(':Version: .*', ':Version: Nikola v{0}'.format(version), os.path.join('docs', 'man', 'nikola.rst')) + man = subprocess.check_output(["rst2man", os.path.join('docs', 'man', 'nikola.rst')]) + with io.open(os.path.join('docs', 'man', 'nikola.1'), 'w', encoding='utf-8') as fh: + try: + man = man.decode('utf-8') + except AttributeError: + pass + fh.write(man) + subprocess.call(["gzip", "-f", os.path.join('docs', 'man', 'nikola.1')]) diff --git a/scripts/update-bower.sh b/scripts/update-bower.sh new file mode 100755 index 0000000..d077434 --- /dev/null +++ b/scripts/update-bower.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# Update all bower packages +bower update + +# Link bootstrap3 theme to bootstrap +pushd nikola/data/themes/bootstrap3/assets/js/ +ln -sf ../../../../../../bower_components/bootstrap/dist/js/*js . +rm npm.js +git add . +popd + +pushd nikola/data/themes/bootstrap3/assets/css/ +ln -sf ../../../../../../bower_components/bootstrap/dist/css/* . +git add . +popd + +pushd nikola/data/themes/bootstrap3/assets/fonts/ +ln -sf ../../../../../../bower_components/bootstrap/dist/fonts/* . +git add . +popd + +# Link moment.js to base theme +pushd nikola/data/themes/base/assets/js +ln -sf ../../../../../../bower_components/moment/min/moment-with-locales.min.js . +git add moment-with-locales.min.js +popd + +# Link jQuery to bootstrap theme +pushd nikola/data/themes/bootstrap/assets/js +ln -sf ../../../../../../bower_components/jquery/dist/* . +git add . +popd + + +# Link colorbox into bootstrap theme +pushd nikola/data/themes/bootstrap/assets/js +ln -sf ../../../../../../bower_components/jquery-colorbox/jquery.colorbox.js . +git add jquery.colorbox.js +popd + +pushd nikola/data/themes/bootstrap/assets/js/colorbox-i18n +ln -sf ../../../../../../../bower_components/jquery-colorbox/i18n/* . +git add . +popd + +pushd nikola/data/themes/bootstrap/assets/css/ +ln -sf ../../../../../../bower_components/jquery-colorbox/example3/colorbox.css . +git add colorbox.css +popd + +pushd nikola/data/themes/bootstrap/assets/css/images/ +ln -sf ../../../../../../../bower_components/jquery-colorbox/example3/images/* . +git add . +popd + +scripts/generate_symlinked_list.sh @@ -1,5 +1,5 @@ [wheel] -universal = 0 +universal = 1 [flake8] ignore=E501 @@ -1,18 +1,12 @@ #!/usr/bin/env python -# find_package data is -# (c) 2005 Ian Bicking and contributors; written for Paste -# (http://pythonpaste.org) -# Licensed under the MIT license: -# http://www.opensource.org/licenses/mit-license.php - # Don't use __future__ in this script, it breaks buildout # from __future__ import print_function import os import subprocess import sys import shutil -from setuptools import setup +from setuptools import setup, find_packages from setuptools.command.install import install from setuptools.command.test import test as TestCommand @@ -44,8 +38,8 @@ with open('requirements-tests.txt', 'r') as fh: extras['tests'] = [l.strip() for l in fh][1:] # ########## platform specific stuff ############# -if sys.version_info[0] == 2 and sys.version_info[1] < 6: - raise Exception('Python 2 version < 2.6 is not supported') +if sys.version_info[0] == 2 and sys.version_info[1] < 7: + raise Exception('Python 2 version < 2.7 is not supported') elif sys.version_info[0] == 3 and sys.version_info[1] < 3: raise Exception('Python 3 version < 3.3 is not supported') @@ -81,7 +75,7 @@ def expands_symlinks_for_windows(): path to the file it points to. If not corrected, installing from a git clone will end with some files with bad content - After install the working copy will be dirty (symlink markers rewroted with + After install the working copy will be dirty (symlink markers overwritten with real content) """ if sys.platform != 'win32': @@ -95,39 +89,13 @@ def expands_symlinks_for_windows(): failures = winutils.fix_all_git_symlinked(localdir) sys.path = oldpath del sys.modules['winutils'] - print('WARNING: your working copy is now dirty by changes in samplesite, sphinx and themes') - if failures: + if failures != -1: + print('WARNING: your working copy is now dirty by changes in samplesite, sphinx and themes') + if failures > 0: raise Exception("Error: \n\tnot all symlinked files could be fixed." + "\n\tYour best bet is to start again from clean.") -def install_manpages(root, prefix): - try: - man_pages = [ - ('docs/man/nikola.1', 'share/man/man1/nikola.1'), - ] - join = os.path.join - normpath = os.path.normpath - if root is not None: - prefix = os.path.realpath(root) + os.path.sep + prefix - for src, dst in man_pages: - path_dst = join(normpath(prefix), normpath(dst)) - try: - os.makedirs(os.path.dirname(path_dst)) - except OSError: - pass - rst2man_cmd = ['rst2man.py', 'rst2man'] - for rst2man in rst2man_cmd: - try: - subprocess.call([rst2man, src, path_dst]) - except OSError: - continue - else: - break - except Exception as e: - print("Not installing the man pages:", e) - - def remove_old_files(self): tree = os.path.join(self.install_lib, 'nikola') try: @@ -141,27 +109,16 @@ class nikola_install(install): expands_symlinks_for_windows() remove_old_files(self) install.run(self) - install_manpages(self.root, self.prefix) setup(name='Nikola', - version='7.1.0', + version='7.6.0', description='A modular, fast, simple, static website generator', long_description=open('README.rst').read(), author='Roberto Alsina and others', author_email='ralsina@netmanagers.com.ar', - url='http://getnikola.com', - packages=['nikola', - 'nikola.plugins', - 'nikola.plugins.command', - 'nikola.plugins.compile', - 'nikola.plugins.compile.ipynb', - 'nikola.plugins.compile.markdown', - 'nikola.plugins.compile.rest', - 'nikola.plugins.task', - 'nikola.plugins.task.sitemap', - 'nikola.plugins.template', - ], + url='https://getnikola.com/', + packages=find_packages(exclude=('tests',)), license='MIT', keywords='website, static', classifiers=('Development Status :: 5 - Production/Stable', @@ -176,7 +133,6 @@ setup(name='Nikola', 'Operating System :: POSIX', 'Operating System :: Unix', 'Programming Language :: Python', - 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', @@ -193,6 +149,7 @@ setup(name='Nikola', 'docs/manual.txt', 'docs/theming.txt', 'docs/extending.txt']), + ('share/man/man1', ['docs/man/nikola.1.gz']), ], entry_points = { 'console_scripts': [ diff --git a/tests/__init__.py b/tests/__init__.py index e69de29..ed1acfa 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1 @@ +# Tests for Nikola. diff --git a/tests/base.py b/tests/base.py index a244f6a..f0bd484 100644 --- a/tests/base.py +++ b/tests/base.py @@ -203,6 +203,7 @@ class FakeSite(object): 'DEFAULT_LANG': 'en', 'MARKDOWN_EXTENSIONS': ['fenced_code', 'codehilite'], 'TRANSLATIONS_PATTERN': '{path}.{lang}.{ext}', + 'LISTINGS_FOLDERS': {'listings': 'listings'}, } self.EXTRA_PLUGINS = self.config['EXTRA_PLUGINS'] self.plugin_manager = PluginManager(categories_filter={ @@ -233,6 +234,7 @@ class FakeSite(object): slug='fake-post') ] self.debug = True + self.rst_transforms = [] # This is to make plugin initialization happy self.template_system = self self.name = 'mako' diff --git a/tests/data/translated_titles/conf.py b/tests/data/translated_titles/conf.py index 4904586..3d0d829 100644 --- a/tests/data/translated_titles/conf.py +++ b/tests/data/translated_titles/conf.py @@ -23,10 +23,10 @@ BLOG_AUTHOR = "Your Name" # (translatable) BLOG_TITLE = "Demo Site" # (translatable) # This is the main URL for your site. It will be used # in a prominent link -SITE_URL = "http://getnikola.com/" +SITE_URL = "https://example.com/" # This is the URL where nikola's output will be deployed. # If not set, defaults to SITE_URL -# BASE_URL = "http://getnikola.com/" +# BASE_URL = "https://example.com/" BLOG_EMAIL = "joe@demo.site" BLOG_DESCRIPTION = "This is a demo site for Nikola." # (translatable) @@ -279,7 +279,7 @@ REDIRECTIONS = [] # By default, there are no filters. # # Many filters are shipped with Nikola. A list is available in the manual: -# <http://getnikola.com/handbook.html#post-processing-filters> +# <https://getnikola.com/handbook.html#post-processing-filters> # FILTERS = { # ".jpg": ["jpegoptim --strip-all -m75 -v %s"], # } @@ -394,7 +394,7 @@ LICENSE = "" # A small copyright notice for the page footer (in HTML). # (translatable) -CONTENT_FOOTER = 'Contents © {date} <a href="mailto:{email}">{author}</a> - Powered by <a href="http://getnikola.com" rel="nofollow">Nikola</a> {license}' +CONTENT_FOOTER = 'Contents © {date} <a href="mailto:{email}">{author}</a> - Powered by <a href="https://getnikola.com/" rel="nofollow">Nikola</a> {license}' # Things that will be passed to CONTENT_FOOTER.format(). This is done # for translatability, as dicts are not formattable. Nikola will @@ -625,8 +625,8 @@ COMMENT_SYSTEM_ID = "nikolademo" # Use content distribution networks for jquery and twitter-bootstrap css and js -# If this is True, jquery is served from the Google CDN and twitter-bootstrap -# is served from the NetDNA CDN +# If this is True, jquery and html5shiv are served from the Google CDN and +# Bootstrap is served from BootstrapCDN (provided by MaxCDN) # Set this to False if you want to host your site without requiring access to # external resources. # USE_CDN = False diff --git a/tests/test_command_import_wordpress.py b/tests/test_command_import_wordpress.py index fafb10c..2c47bc3 100644 --- a/tests/test_command_import_wordpress.py +++ b/tests/test_command_import_wordpress.py @@ -25,29 +25,6 @@ class BasicCommandImportWordpress(BaseTestCase): del self.import_filename -class TestXMLGlueing(BasicCommandImportWordpress): - def test_making_correct_newlines(self): - xml = [b"Some information about how to (un)subscripe to a google group with a normal mail client.\n", - b"<ul>\n", - b" <li>to post: <strong>groupname@googlegroups.com</strong></li>\n", - b" <li>to <em>subscribe</em>: <strong>groupname+subscribe@googlegroups.com</strong></li>\n", - b" <li>to <em>unsubscribe</em>: <strong>groupname+unsubscribe@googlegroups.com</strong></li>\n", - b"</ul>\n", - b"Easy.\n"] - - expected_xml = b"""Some information about how to (un)subscripe to a google group with a normal mail client. - -<ul> - <li>to post: <strong>groupname@googlegroups.com</strong></li> - <li>to <em>subscribe</em>: <strong>groupname+subscribe@googlegroups.com</strong></li> - <li>to <em>unsubscribe</em>: <strong>groupname+unsubscribe@googlegroups.com</strong></li> -</ul> - -Easy. -""" - self.assertEqual(expected_xml, self.import_command._glue_xml_lines(xml)) - - class TestQTranslateContentSeparation(BasicCommandImportWordpress): def test_conserves_qtranslate_less_post(self): @@ -241,7 +218,7 @@ class CommandImportWordpressTest(BasicCommandImportWordpress): self.assertTrue(write_metadata.called) write_metadata.assert_any_call( 'new_site/stories/kontakt.meta'.replace('/', os.sep), 'Kontakt', - 'kontakt', '2009-07-16 20:20:32', None, []) + 'kontakt', '2009-07-16 20:20:32', '', []) self.assertTrue(write_content.called) write_content.assert_any_call('new_site/posts/2007/04/hoert.wp'.replace('/', os.sep), @@ -251,13 +228,13 @@ class CommandImportWordpressTest(BasicCommandImportWordpress): Some source code. -~~~~~~~~~~~~{.Python} +```Python import sys print sys.version -~~~~~~~~~~~~ +``` The end. @@ -266,17 +243,25 @@ The end. write_content.assert_any_call( 'new_site/posts/2008/07/arzt-und-pfusch-s-i-c-k.wp'.replace('/', os.sep), '''<img class="size-full wp-image-10 alignright" title="Arzt+Pfusch - S.I.C.K." src="http://some.blog/wp-content/uploads/2008/07/arzt_und_pfusch-sick-cover.png" alt="Arzt+Pfusch - S.I.C.K." width="210" height="209" />Arzt+Pfusch - S.I.C.K.Gerade bin ich \xfcber das Album <em>S.I.C.K</em> von <a title="Arzt+Pfusch" href="http://www.arztpfusch.com/" target="_blank">Arzt+Pfusch</a> gestolpert, welches Arzt+Pfusch zum Download f\xfcr lau anbieten. Das Album steht unter einer Creative Commons <a href="http://creativecommons.org/licenses/by-nc-nd/3.0/de/">BY-NC-ND</a>-Lizenz. + Die Ladung <em>noisebmstupidevildustrial</em> gibts als MP3s mit <a href="http://www.archive.org/download/dmp005/dmp005_64kb_mp3.zip">64kbps</a> und <a href="http://www.archive.org/download/dmp005/dmp005_vbr_mp3.zip">VBR</a>, als Ogg Vorbis und als FLAC (letztere <a href="http://www.archive.org/details/dmp005">hier</a>). <a href="http://www.archive.org/download/dmp005/dmp005-artwork.zip">Artwork</a> und <a href="http://www.archive.org/download/dmp005/dmp005-lyrics.txt">Lyrics</a> gibts nochmal einzeln zum Download.''') write_content.assert_any_call( 'new_site/stories/kontakt.wp'.replace('/', os.sep), """<h1>Datenschutz</h1> + Ich erhebe und speichere automatisch in meine Server Log Files Informationen, die dein Browser an mich \xfcbermittelt. Dies sind: <ul> + <li>Browsertyp und -version</li> + <li>verwendetes Betriebssystem</li> + <li>Referrer URL (die zuvor besuchte Seite)</li> + <li>IP Adresse des zugreifenden Rechners</li> + <li>Uhrzeit der Serveranfrage.</li> + </ul> Diese Daten sind f\xfcr mich nicht bestimmten Personen zuordenbar. Eine Zusammenf\xfchrung dieser Daten mit anderen Datenquellen wird nicht vorgenommen, die Daten werden einzig zu statistischen Zwecken erhoben.""") @@ -317,16 +302,16 @@ Diese Daten sind f\xfcr mich nicht bestimmten Personen zuordenbar. Eine Zusammen def test_transforming_content(self): """Applying markup conversions to content.""" - transform_sourcecode = mock.MagicMock() + transform_code = mock.MagicMock() transform_caption = mock.MagicMock() transform_newlines = mock.MagicMock() - with mock.patch('nikola.plugins.command.import_wordpress.CommandImportWordpress.transform_sourcecode', transform_sourcecode): + with mock.patch('nikola.plugins.command.import_wordpress.CommandImportWordpress.transform_code', transform_code): with mock.patch('nikola.plugins.command.import_wordpress.CommandImportWordpress.transform_caption', transform_caption): with mock.patch('nikola.plugins.command.import_wordpress.CommandImportWordpress.transform_multiple_newlines', transform_newlines): self.import_command.transform_content("random content") - self.assertTrue(transform_sourcecode.called) + self.assertTrue(transform_code.called) self.assertTrue(transform_caption.called) self.assertTrue(transform_newlines.called) @@ -340,21 +325,18 @@ import sys print sys.version [/sourcecode]""" - content = self.import_command.transform_sourcecode(content) + content = self.import_command.transform_code(content) self.assertFalse('[/sourcecode]' in content) self.assertFalse('[sourcecode language=' in content) replaced_content = """Hello World. - -~~~~~~~~~~~~{.Python} +```Python import sys print sys.version -~~~~~~~~~~~~ -""" - +```""" self.assertEqual(content, replaced_content) def test_transform_caption(self): diff --git a/tests/test_integration.py b/tests/test_integration.py index 28b2965..62ccd79 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -33,8 +33,8 @@ class EmptyBuildTest(BaseTestCase): @classmethod def setUpClass(cls): """Setup a demo site.""" - # for tests that need bilingual support override languaje_settings - cls.languaje_settings() + # for tests that need bilingual support override language_settings + cls.language_settings() cls.startdir = os.getcwd() cls.tmpdir = tempfile.mkdtemp() cls.target_dir = os.path.join(cls.tmpdir, "target") @@ -44,7 +44,7 @@ class EmptyBuildTest(BaseTestCase): cls.build() @classmethod - def languaje_settings(cls): + def language_settings(cls): LocaleSupportInTesting.initialize_locales_for_testing("unilingual") @classmethod @@ -116,12 +116,12 @@ class DemoBuildTest(EmptyBuildTest): def test_index_in_sitemap(self): sitemap_path = os.path.join(self.target_dir, "output", "sitemap.xml") sitemap_data = io.open(sitemap_path, "r", encoding="utf8").read() - self.assertTrue('<loc>http://getnikola.com/index.html</loc>' in sitemap_data) + self.assertTrue('<loc>https://example.com/index.html</loc>' in sitemap_data) def test_avoid_double_slash_in_rss(self): rss_path = os.path.join(self.target_dir, "output", "rss.xml") rss_data = io.open(rss_path, "r", encoding="utf8").read() - self.assertFalse('http://getnikola.com//' in rss_data) + self.assertFalse('https://example.com//' in rss_data) class RepeatedPostsSetting(DemoBuildTest): @@ -193,9 +193,9 @@ class TranslatedBuildTest(EmptyBuildTest): dataname = "translated_titles" @classmethod - def languaje_settings(cls): + def language_settings(cls): LocaleSupportInTesting.initialize_locales_for_testing("bilingual") - # the other languaje + # the other language cls.ol = LocaleSupportInTesting.langlocales["other"][0] def test_translated_titles(self): @@ -272,8 +272,8 @@ class RelativeLinkTest(DemoBuildTest): conf_path = os.path.join(self.target_dir, "conf.py") with io.open(conf_path, "r", encoding="utf-8") as inf: data = inf.read() - data = data.replace('SITE_URL = "http://getnikola.com/"', - 'SITE_URL = "http://getnikola.com/foo/bar/"') + data = data.replace('SITE_URL = "https://example.com/"', + 'SITE_URL = "https://example.com/foo/bar/"') with io.open(conf_path, "w+", encoding="utf8") as outf: outf.write(data) @@ -295,8 +295,8 @@ class RelativeLinkTest(DemoBuildTest): """Test that the correct path is in sitemap, and not the wrong one.""" sitemap_path = os.path.join(self.target_dir, "output", "sitemap.xml") sitemap_data = io.open(sitemap_path, "r", encoding="utf8").read() - self.assertFalse('<loc>http://getnikola.com/</loc>' in sitemap_data) - self.assertTrue('<loc>http://getnikola.com/foo/bar/index.html</loc>' in sitemap_data) + self.assertFalse('<loc>https://example.com/</loc>' in sitemap_data) + self.assertTrue('<loc>https://example.com/foo/bar/index.html</loc>' in sitemap_data) class TestCheck(DemoBuildTest): @@ -321,7 +321,7 @@ class TestCheckAbsoluteSubFolder(TestCheck): """Validate links in a site which is: * built in URL_TYPE="absolute" - * deployable to a subfolder (BASE_URL="http://getnikola.com/foo/") + * deployable to a subfolder (BASE_URL="https://example.com/foo/") """ @classmethod @@ -329,8 +329,8 @@ class TestCheckAbsoluteSubFolder(TestCheck): conf_path = os.path.join(self.target_dir, "conf.py") with io.open(conf_path, "r", encoding="utf-8") as inf: data = inf.read() - data = data.replace('SITE_URL = "http://getnikola.com/"', - 'SITE_URL = "http://getnikola.com/foo/"') + data = data.replace('SITE_URL = "https://example.com/"', + 'SITE_URL = "https://example.com/foo/"') data = data.replace("# URL_TYPE = 'rel_path'", "URL_TYPE = 'absolute'") with io.open(conf_path, "w+", encoding="utf8") as outf: @@ -341,14 +341,14 @@ class TestCheckAbsoluteSubFolder(TestCheck): """Test that the correct path is in sitemap, and not the wrong one.""" sitemap_path = os.path.join(self.target_dir, "output", "sitemap.xml") sitemap_data = io.open(sitemap_path, "r", encoding="utf8").read() - self.assertTrue('<loc>http://getnikola.com/foo/index.html</loc>' in sitemap_data) + self.assertTrue('<loc>https://example.com/foo/index.html</loc>' in sitemap_data) class TestCheckFullPathSubFolder(TestCheckAbsoluteSubFolder): """Validate links in a site which is: * built in URL_TYPE="full_path" - * deployable to a subfolder (BASE_URL="http://getnikola.com/foo/") + * deployable to a subfolder (BASE_URL="https://example.com/foo/") """ @classmethod @@ -356,8 +356,8 @@ class TestCheckFullPathSubFolder(TestCheckAbsoluteSubFolder): conf_path = os.path.join(self.target_dir, "conf.py") with io.open(conf_path, "r", encoding="utf-8") as inf: data = inf.read() - data = data.replace('SITE_URL = "http://getnikola.com/"', - 'SITE_URL = "http://getnikola.com/foo/"') + data = data.replace('SITE_URL = "https://example.com/"', + 'SITE_URL = "https://example.com/foo/"') data = data.replace("# URL_TYPE = 'rel_path'", "URL_TYPE = 'full_path'") with io.open(conf_path, "w+", encoding="utf8") as outf: @@ -423,8 +423,8 @@ class RelativeLinkTest2(DemoBuildTest): """Test that the correct path is in sitemap, and not the wrong one.""" sitemap_path = os.path.join(self.target_dir, "output", "sitemap.xml") sitemap_data = io.open(sitemap_path, "r", encoding="utf8").read() - self.assertFalse('<loc>http://getnikola.com/</loc>' in sitemap_data) - self.assertTrue('<loc>http://getnikola.com/blog/index.html</loc>' in sitemap_data) + self.assertFalse('<loc>https://example.com/</loc>' in sitemap_data) + self.assertTrue('<loc>https://example.com/blog/index.html</loc>' in sitemap_data) class MonthlyArchiveTest(DemoBuildTest): @@ -447,6 +447,49 @@ class MonthlyArchiveTest(DemoBuildTest): self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, 'target', 'output', '2012', '03', 'index.html'))) +class DayArchiveTest(DemoBuildTest): + """Check that per-day archives build and are correct.""" + + @classmethod + def patch_site(self): + """Set the SITE_URL to have a path""" + conf_path = os.path.join(self.target_dir, "conf.py") + with io.open(conf_path, "r", encoding="utf-8") as inf: + data = inf.read() + data = data.replace('# CREATE_DAILY_ARCHIVE = False', + 'CREATE_DAILY_ARCHIVE = True') + with io.open(conf_path, "w+", encoding="utf8") as outf: + outf.write(data) + outf.flush() + + def test_day_archive(self): + """See that it builds""" + self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, 'target', 'output', '2012', '03', '30', 'index.html'))) + + +class FullArchiveTest(DemoBuildTest): + """Check that full archives build and are correct.""" + + @classmethod + def patch_site(self): + """Set the SITE_URL to have a path""" + conf_path = os.path.join(self.target_dir, "conf.py") + with io.open(conf_path, "r", encoding="utf-8") as inf: + data = inf.read() + data = data.replace('# CREATE_FULL_ARCHIVES = False', + 'CREATE_FULL_ARCHIVES = True') + with io.open(conf_path, "w+", encoding="utf8") as outf: + outf.write(data) + outf.flush() + + def test_full_archive(self): + """See that it builds""" + self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, 'target', 'output', 'archive.html'))) + self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, 'target', 'output', '2012', 'index.html'))) + self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, 'target', 'output', '2012', '03', 'index.html'))) + self.assertTrue(os.path.isfile(os.path.join(self.tmpdir, 'target', 'output', '2012', '03', '30', 'index.html'))) + + class SubdirRunningTest(DemoBuildTest): """Check that running nikola from subdir works.""" @@ -502,5 +545,50 @@ class InvariantBuildTest(EmptyBuildTest): self.assertEqual(exc.returncode, 0, 'Unexplained diff for the invariance test.') +class RedirectionsTest1(TestCheck): + """Check REDIRECTIONS""" + + @classmethod + def patch_site(self): + """""" + conf_path = os.path.join(self.target_dir, "conf.py") + with io.open(conf_path, "a", encoding="utf8") as outf: + outf.write("""\n\nREDIRECTIONS = [ ("posts/foo.html", "/foo/bar.html"), ]\n\n""") + + @classmethod + def fill_site(self): + target_path = os.path.join(self.target_dir, "files", "foo", "bar.html") + nikola.utils.makedirs(os.path.join(self.target_dir, "files", "foo")) + with io.open(target_path, "w+", encoding="utf8") as outf: + outf.write("foo") + +class RedirectionsTest2(TestCheck): + """Check external REDIRECTIONS""" + + @classmethod + def patch_site(self): + """""" + conf_path = os.path.join(self.target_dir, "conf.py") + with io.open(conf_path, "a", encoding="utf8") as outf: + outf.write("""\n\nREDIRECTIONS = [ ("foo.html", "http://www.example.com/"), ]\n\n""") + +class RedirectionsTest3(TestCheck): + """Check relative REDIRECTIONS""" + + @classmethod + def patch_site(self): + """""" + conf_path = os.path.join(self.target_dir, "conf.py") + with io.open(conf_path, "a", encoding="utf8") as outf: + outf.write("""\n\nREDIRECTIONS = [ ("foo.html", "foo/bar.html"), ]\n\n""") + + @classmethod + def fill_site(self): + target_path = os.path.join(self.target_dir, "files", "foo", "bar.html") + nikola.utils.makedirs(os.path.join(self.target_dir, "files", "foo")) + with io.open(target_path, "w+", encoding="utf8") as outf: + outf.write("foo") + + if __name__ == "__main__": unittest.main() diff --git a/tests/test_rss_feeds.py b/tests/test_rss_feeds.py index 5eeb570..992b1b7 100644 --- a/tests/test_rss_feeds.py +++ b/tests/test_rss_feeds.py @@ -33,6 +33,13 @@ class FakeCompiler(object): demote_headers = False compile_html = None extension = lambda self: '.html' + name = "fake" + + def read_metadata(*args, **kwargs): + return {} + + def register_extra_dependencies(self, post): + pass class RSSFeedTest(unittest.TestCase): @@ -42,14 +49,14 @@ class RSSFeedTest(unittest.TestCase): with mock.patch('nikola.post.get_meta', mock.Mock(return_value=( - {'title': 'post title', + ({'title': 'post title', 'slug': 'awesome_article', 'date': '2012-10-01 22:41', 'author': None, 'tags': 'tags', 'link': 'link', 'description': 'description', - 'enclosure': 'http://www.example.org/foo.mp3'} + 'enclosure': 'http://www.example.org/foo.mp3'}, True) ))): with mock.patch('nikola.nikola.utils.os.path.isdir', mock.Mock(return_value=True)): diff --git a/tests/test_rst_compiler.py b/tests/test_rst_compiler.py index 1747332..5bbd617 100644 --- a/tests/test_rst_compiler.py +++ b/tests/test_rst_compiler.py @@ -122,8 +122,8 @@ class ReSTExtensionTestCaseTestCase(ReSTExtensionTestCase): class MathTestCase(ReSTExtensionTestCase): sample = ':math:`e^{ix} = \cos x + i\sin x`' - def test_mathjax(self): - """ Test that math is outputting MathJax.""" + def test_math(self): + """ Test that math is outputting TeX code.""" self.basic_test() self.assertHTMLContains("span", attributes={"class": "math"}, text="\(e^{ix} = \cos x + i\sin x\)") diff --git a/tests/test_utils.py b/tests/test_utils.py index c392c02..1e2d3b3 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -34,7 +34,7 @@ class GetMetaTest(unittest.TestCase): post.metadata_path = 'file_with_metadata.meta' with mock.patch('nikola.post.io.open', opener_mock, create=True): - meta = get_meta(post) + meta, nsm = get_meta(post) self.assertEqual('Nikola needs more tests!', meta['title']) self.assertEqual('write-tests-now', meta['slug']) @@ -42,6 +42,7 @@ class GetMetaTest(unittest.TestCase): self.assertFalse('tags' in meta) self.assertFalse('link' in meta) self.assertFalse('description' in meta) + self.assertTrue(nsm) def test_get_title_from_rest(self): file_metadata = [".. slug: write-tests-now\n", @@ -60,7 +61,7 @@ class GetMetaTest(unittest.TestCase): post.metadata_path = 'file_with_metadata.meta' with mock.patch('nikola.post.io.open', opener_mock, create=True): - meta = get_meta(post) + meta, nsm = get_meta(post) self.assertEqual('Post Title', meta['title']) self.assertEqual('write-tests-now', meta['slug']) @@ -68,6 +69,7 @@ class GetMetaTest(unittest.TestCase): self.assertFalse('tags' in meta) self.assertFalse('link' in meta) self.assertFalse('description' in meta) + self.assertTrue(nsm) def test_get_title_from_fname(self): file_metadata = [".. slug: write-tests-now\n", @@ -84,7 +86,7 @@ class GetMetaTest(unittest.TestCase): post.metadata_path = 'file_with_metadata.meta' with mock.patch('nikola.post.io.open', opener_mock, create=True): - meta = get_meta(post, 'file_with_metadata') + meta, nsm = get_meta(post, 'file_with_metadata') self.assertEqual('file_with_metadata', meta['title']) self.assertEqual('write-tests-now', meta['slug']) @@ -92,6 +94,7 @@ class GetMetaTest(unittest.TestCase): self.assertFalse('tags' in meta) self.assertFalse('link' in meta) self.assertFalse('description' in meta) + self.assertTrue(nsm) def test_use_filename_as_slug_fallback(self): file_metadata = [".. title: Nikola needs more tests!\n", @@ -109,7 +112,7 @@ class GetMetaTest(unittest.TestCase): post.metadata_path = 'Slugify this.meta' with mock.patch('nikola.post.io.open', opener_mock, create=True): - meta = get_meta(post, 'Slugify this') + meta, nsm = get_meta(post, 'Slugify this') self.assertEqual('Nikola needs more tests!', meta['title']) self.assertEqual('slugify-this', meta['slug']) @@ -117,13 +120,14 @@ class GetMetaTest(unittest.TestCase): self.assertFalse('tags' in meta) self.assertFalse('link' in meta) self.assertFalse('description' in meta) + self.assertTrue(nsm) def test_extracting_metadata_from_filename(self): post = dummy() post.source_path = '2013-01-23-the_slug-dubdubtitle.md' post.metadata_path = '2013-01-23-the_slug-dubdubtitle.meta' with mock.patch('nikola.post.io.open', create=True): - meta = get_meta( + meta, _ = get_meta( post, '(?P<date>\d{4}-\d{2}-\d{2})-(?P<slug>.*)-(?P<title>.*)\.md') @@ -136,7 +140,7 @@ class GetMetaTest(unittest.TestCase): post.source_path = 'some/path/the_slug.md' post.metadata_path = 'some/path/the_slug.meta' with mock.patch('nikola.post.io.open', create=True): - meta = get_meta(post) + meta, _ = get_meta(post) self.assertEqual('the_slug', meta['slug']) @@ -246,7 +250,7 @@ class TranslatableSettingsTest(unittest.TestCase): except NameError: # Python 3 u = str(S) - cn = S() # no language specified + cn = S() # no language specified cr = S('xx') # real language specified cf = S('zz') # fake language specified diff --git a/translations/nikola.messages/ar.po b/translations/nikola.messages/ar.po index 907d667..5a6cc86 100644 --- a/translations/nikola.messages/ar.po +++ b/translations/nikola.messages/ar.po @@ -6,14 +6,16 @@ # Translators: # Translators: # Translators: +# Translators: +# Mohammed Attia <skeuomorf@gmail.com>, 2014 # darkwise <za3boud@yahoo.fr>, 2014 msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-08-14 21:30+0000\n" -"Last-Translator: darkwise <za3boud@yahoo.fr>\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Arabic (http://www.transifex.com/projects/p/nikola/language/ar/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -24,17 +26,19 @@ msgstr "" msgid "More posts about %s" msgstr "المزيد من المقالات حول %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "العربيّة" msgid "Tags" -msgstr "" +msgstr "تصنيفات" msgid "Categories" -msgstr "الأصناف" +msgstr "فئات" msgid "Tags and Categories" -msgstr "" +msgstr "تصنيفات و فئات" msgid "Comments" msgstr "التّعليقات" @@ -43,63 +47,66 @@ msgid "Read more" msgstr "قراءة المزيد" msgid "Posts about %s" -msgstr "" +msgstr "مقالات عن s%" msgid "Next post" -msgstr "" +msgstr "المقالة التالية" msgid "old posts, page %d" -msgstr "" +msgstr "مقالات قديمة, صفحة d%" msgid "page %d" -msgstr "" +msgstr "صفحة d%" msgid "Source" -msgstr "" +msgstr "المصدر" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" -msgstr "" +msgstr "اقرأ بالعربية" msgid "Posts for year %s" -msgstr "" +msgstr "مقالات سنة s%" msgid "Newer posts" -msgstr "" +msgstr "مقالات أحدث" msgid "Previous post" -msgstr "" +msgstr "المقالة السابقة" msgid "Also available in:" -msgstr "" +msgstr "أيضا متوفر في:" msgid "Languages:" -msgstr "" +msgstr "اللغات" msgid "Original site" -msgstr "" +msgstr "الموقع الأصلي" msgid "Older posts" -msgstr "" +msgstr "مقالات أقدم" msgid "Archive" -msgstr "" +msgstr "الأرشيف" msgid "Publication date" -msgstr "" +msgstr "تاريخ النشر" msgid "Posted:" -msgstr "" +msgstr "نشر:" msgid "Posts for {month} {year}" msgstr "" -msgid "Nothing found." +msgid "Posts for {month} {day}, {year}" msgstr "" +msgid "Nothing found." +msgstr "لم يوجد شيء." + msgid "No posts found." -msgstr "" +msgstr "لم يوجد مقالات." msgid "RSS feed" msgstr "" @@ -108,4 +115,19 @@ msgid "%d min remaining to read" msgstr "" msgid "Skip to main content" +msgstr "انتقل إلى المحتوى الرئيسي" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/az.po b/translations/nikola.messages/az.po new file mode 100644 index 0000000..6b72895 --- /dev/null +++ b/translations/nikola.messages/az.po @@ -0,0 +1,132 @@ +# Messages in Nikola +# Copyright (C) 2012-2013 +# This file is distributed under the same license as the Nikola package. +# +# Translators: +# Translators: +# Translators: +# Translators: +# Translators: +# knulp <knulphaller@gmail.com>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: Nikola\n" +"Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" +"POT-Creation-Date: 2013-03-15 12:24-0300\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" +"Language-Team: Azerbaijani (http://www.transifex.com/projects/p/nikola/language/az/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: az\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "More posts about %s" +msgstr "%s ilə bağlı digər yazılar" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "LANGUAGE" +msgstr "Azərbaycan dili" + +msgid "Tags" +msgstr "Teqlər" + +msgid "Categories" +msgstr "Kateqoriyalar" + +msgid "Tags and Categories" +msgstr "Teqlər və Kateqoriyalar" + +msgid "Comments" +msgstr "Şərhlər" + +msgid "Read more" +msgstr "Davamı" + +msgid "Posts about %s" +msgstr "%s ilə bağlı yazılar" + +msgid "Next post" +msgstr "Növbəti yazı" + +msgid "old posts, page %d" +msgstr "köhnə yazılar, səhifə %s" + +msgid "page %d" +msgstr "səhifə %d" + +msgid "Source" +msgstr "Mənbə" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "Read in English" +msgstr "Azərbaycan dilində oxu" + +msgid "Posts for year %s" +msgstr "%s ilindəki yazılar" + +msgid "Newer posts" +msgstr "Yeni yazılar" + +msgid "Previous post" +msgstr "Əvvəlki yazı" + +msgid "Also available in:" +msgstr "Həmçinin mövcuddur:" + +msgid "Languages:" +msgstr "Dillər:" + +msgid "Original site" +msgstr "Original sayt" + +msgid "Older posts" +msgstr "Köhnə yazılar" + +msgid "Archive" +msgstr "Arxiv" + +msgid "Publication date" +msgstr "Buraxılış tarixi" + +msgid "Posted:" +msgstr "yazılma tarixi:" + +msgid "Posts for {month} {year}" +msgstr "{month} {year} üçün yazılar" + +msgid "Posts for {month} {day}, {year}" +msgstr "{month} {day}, {year} üçün yazılar" + +msgid "Nothing found." +msgstr "Heç nə tapılmadı" + +msgid "No posts found." +msgstr "Heç bir yazı tapılmadı" + +msgid "RSS feed" +msgstr "RSS" + +msgid "%d min remaining to read" +msgstr "%d dəqiqəlik oxuma" + +msgid "Skip to main content" +msgstr "Əsas mövzuya keç" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/bg.po b/translations/nikola.messages/bg.po index 1934b78..ac5b292 100644 --- a/translations/nikola.messages/bg.po +++ b/translations/nikola.messages/bg.po @@ -6,6 +6,7 @@ # Translators: # Translators: # Translators: +# Translators: # Ivaylo Kuzev <ivkuzev@gmail.com>, 2013 # Ivaylo Kuzev <ivkuzev@gmail.com>, 2013 msgid "" @@ -13,7 +14,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Bulgarian (http://www.transifex.com/projects/p/nikola/language/bg/)\n" "MIME-Version: 1.0\n" @@ -25,6 +26,8 @@ msgstr "" msgid "More posts about %s" msgstr "Още публикации относно %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Български" @@ -58,7 +61,7 @@ msgstr "страница %d" msgid "Source" msgstr "Source" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Прочетете на български" @@ -96,6 +99,9 @@ msgstr "Публиковано:" msgid "Posts for {month} {year}" msgstr "Публикации за {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "" + msgid "Nothing found." msgstr "" @@ -110,3 +116,18 @@ msgstr "" msgid "Skip to main content" msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/ca.po b/translations/nikola.messages/ca.po index 497e07f..7134b2c 100644 --- a/translations/nikola.messages/ca.po +++ b/translations/nikola.messages/ca.po @@ -6,6 +6,8 @@ # Translators: # Translators: # Translators: +# Translators: +# Alfons Rovira <inclusa@gmail.com>, 2014 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 msgid "" @@ -13,7 +15,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Catalan (http://www.transifex.com/projects/p/nikola/language/ca/)\n" "MIME-Version: 1.0\n" @@ -25,6 +27,8 @@ msgstr "" msgid "More posts about %s" msgstr "Més entrades sobre %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Català" @@ -32,13 +36,13 @@ msgid "Tags" msgstr "Etiquetes" msgid "Categories" -msgstr "" +msgstr "Categories" msgid "Tags and Categories" -msgstr "" +msgstr "Etiquetes i Categories" msgid "Comments" -msgstr "" +msgstr "Comentaris" msgid "Read more" msgstr "Llegeix-ne més" @@ -58,7 +62,7 @@ msgstr "pàgina %d" msgid "Source" msgstr "Codi" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Llegeix-ho en català" @@ -76,7 +80,7 @@ msgid "Also available in:" msgstr "També disponibles en:" msgid "Languages:" -msgstr "" +msgstr "Llenguatges:" msgid "Original site" msgstr "Lloc original" @@ -88,25 +92,43 @@ msgid "Archive" msgstr "Arxiu" msgid "Publication date" -msgstr "" +msgstr "Data de publicació" msgid "Posted:" msgstr "Publicat:" msgid "Posts for {month} {year}" +msgstr "Publicat en {month} {year}" + +msgid "Posts for {month} {day}, {year}" msgstr "" msgid "Nothing found." -msgstr "" +msgstr "No trobat" msgid "No posts found." -msgstr "" +msgstr "Publicació no trobada" msgid "RSS feed" -msgstr "" +msgstr "Feed RSS" msgid "%d min remaining to read" -msgstr "" +msgstr "% min recordar per a llegir" msgid "Skip to main content" +msgstr "Vés al comentari principal" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/cs.po b/translations/nikola.messages/cs.po index 022f43b..6bbe808 100644 --- a/translations/nikola.messages/cs.po +++ b/translations/nikola.messages/cs.po @@ -6,14 +6,16 @@ # Translators: # Translators: # Translators: -# Jaroslav Lichtblau <jaroslav@lichtblau.cz>, 2014 +# Translators: +# Jaroslav Lichtblau <dragonlord@seznam.cz>, 2014 +# Jaroslav Lichtblau <dragonlord@seznam.cz>, 2014 # smartass <ondrej.grover@gmail.com>, 2014 msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Czech (http://www.transifex.com/projects/p/nikola/language/cs/)\n" "MIME-Version: 1.0\n" @@ -25,6 +27,8 @@ msgstr "" msgid "More posts about %s" msgstr "Další příspěvky o %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Čeština" @@ -58,7 +62,7 @@ msgstr "strana %d" msgid "Source" msgstr "Zdroj" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Číst v češtině" @@ -96,6 +100,9 @@ msgstr "Zveřejněno:" msgid "Posts for {month} {year}" msgstr "Příspěvky v {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "Příspěvky v {month} {day}, {year}" + msgid "Nothing found." msgstr "Nic nebylo nalezeno." @@ -109,4 +116,19 @@ msgid "%d min remaining to read" msgstr "%d min zbývajících" msgid "Skip to main content" +msgstr "Přeskočit na hlavní obsah" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/da.po b/translations/nikola.messages/da.po index 78548b3..80dca87 100644 --- a/translations/nikola.messages/da.po +++ b/translations/nikola.messages/da.po @@ -6,12 +6,16 @@ # Translators: # Translators: # Translators: +# Translators: +# Chris Warrick <kwpolska@gmail.com>, 2014 +# Joe Hansen <joedalton2@yahoo.dk>, 2014 +# Michael Götzsche Dougherty <zombient@gmail.com>, 2014 msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Danish (http://www.transifex.com/projects/p/nikola/language/da/)\n" "MIME-Version: 1.0\n" @@ -21,90 +25,110 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "More posts about %s" -msgstr "" +msgstr "Yderligere indlæg om %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" -msgstr "" +msgstr "Dansk" msgid "Tags" -msgstr "" +msgstr "Nøgleord" msgid "Categories" -msgstr "" +msgstr "Kategorier" msgid "Tags and Categories" -msgstr "" +msgstr "Nøgleord og kategorier" msgid "Comments" -msgstr "" +msgstr "Kommentarer" msgid "Read more" -msgstr "" +msgstr "Læs mere" msgid "Posts about %s" -msgstr "" +msgstr "Indlæg om %s" msgid "Next post" -msgstr "" +msgstr "Næste indlæg" msgid "old posts, page %d" -msgstr "" +msgstr "gamle indlæg, side %d" msgid "page %d" -msgstr "" +msgstr "side %d" msgid "Source" -msgstr "" +msgstr "Kilde" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" -msgstr "" +msgstr "Læs på dansk" msgid "Posts for year %s" -msgstr "" +msgstr "Indlæg for %s" msgid "Newer posts" -msgstr "" +msgstr "Nyere indlæg" msgid "Previous post" -msgstr "" +msgstr "Tidligere indlæg" msgid "Also available in:" -msgstr "" +msgstr "Fås også i:" msgid "Languages:" -msgstr "" +msgstr "Sprog:" msgid "Original site" -msgstr "" +msgstr "Oprindeligt hjemmeside" msgid "Older posts" -msgstr "" +msgstr "Ældre indlæg" msgid "Archive" -msgstr "" +msgstr "Arkiv" msgid "Publication date" -msgstr "" +msgstr "Udgivelsesdato" msgid "Posted:" -msgstr "" +msgstr "Opslået:" msgid "Posts for {month} {year}" -msgstr "" +msgstr "Indlæg for {month} {year}" + +msgid "Posts for {month} {day}, {year}" +msgstr "Indlæs for {month} {day}, {year}" msgid "Nothing found." -msgstr "" +msgstr "Søgningen gav ingen resultater." msgid "No posts found." -msgstr "" +msgstr "Søgningen gav ingen resultater." msgid "RSS feed" -msgstr "" +msgstr "RSS-nyhedskilde" msgid "%d min remaining to read" -msgstr "" +msgstr "%d min. tilbage at læse" msgid "Skip to main content" +msgstr "Hop direkte til hovedindhold" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/de.po b/translations/nikola.messages/de.po index 68d3525..03acfdf 100644 --- a/translations/nikola.messages/de.po +++ b/translations/nikola.messages/de.po @@ -6,9 +6,12 @@ # Translators: # Translators: # Translators: +# Translators: +# amokleben <wenso@gmx.de>, 2013 # Chris Warrick <kwpolska@gmail.com>, 2013-2014 # Chris Warrick <kwpolska@gmail.com>, 2013 # Chris Warrick <kwpolska@gmail.com>, 2013 +# Martin Bless <martin.bless@gmail.com>, 2014 # amokleben <wenso@gmx.de>, 2013 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 @@ -20,7 +23,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: German (http://www.transifex.com/projects/p/nikola/language/de/)\n" "MIME-Version: 1.0\n" @@ -32,6 +35,8 @@ msgstr "" msgid "More posts about %s" msgstr "Weitere Einträge über %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Deutsch" @@ -65,7 +70,7 @@ msgstr "Seite %d" msgid "Source" msgstr "Source" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Auf Deutsch lesen" @@ -103,6 +108,9 @@ msgstr "Veröffentlicht:" msgid "Posts for {month} {year}" msgstr "Einträge aus {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "Einträge vom {day}. {month} {year}" + msgid "Nothing found." msgstr "Nichts gefunden." @@ -116,4 +124,19 @@ msgid "%d min remaining to read" msgstr "%d min verbleiben zum Lesen" msgid "Skip to main content" +msgstr "Springe zum Hauptinhalt" + +msgid "Subcategories:" +msgstr "Unterkategorien:" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/el.po b/translations/nikola.messages/el.po index 5af8fbe..1baf2f1 100644 --- a/translations/nikola.messages/el.po +++ b/translations/nikola.messages/el.po @@ -6,7 +6,8 @@ # Translators: # Translators: # Translators: -# Panagiotis Mavrogiorgos <otinanai90@gmail.com>, 2013 +# Translators: +# Panagiotis Mavrogiorgos <otinanai90@gmail.com>, 2013,2015 # Panagiotis Mavrogiorgos <otinanai90@gmail.com>, 2013 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 @@ -15,7 +16,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Greek (http://www.transifex.com/projects/p/nikola/language/el/)\n" "MIME-Version: 1.0\n" @@ -27,6 +28,8 @@ msgstr "" msgid "More posts about %s" msgstr "Περισσότερες αναρτήσεις για %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Ελληνικά" @@ -40,7 +43,7 @@ msgid "Tags and Categories" msgstr "Ετικέτες και κατηγορίες" msgid "Comments" -msgstr "" +msgstr "Σχόλια" msgid "Read more" msgstr "Διαβάστε περισσότερα" @@ -60,7 +63,7 @@ msgstr "σελίδα %d" msgid "Source" msgstr "Πηγαίος κώδικας" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Διαβάστε στα Ελληνικά" @@ -78,7 +81,7 @@ msgid "Also available in:" msgstr "Διαθέσιμο και στα:" msgid "Languages:" -msgstr "" +msgstr "Γλώσσες" msgid "Original site" msgstr "Ιστοσελίδα αρχικής ανάρτησης" @@ -90,7 +93,7 @@ msgid "Archive" msgstr "Αρχείο" msgid "Publication date" -msgstr "" +msgstr "Ημερομηνία δημοσίευσης" msgid "Posted:" msgstr "Αναρτήθηκε:" @@ -98,11 +101,14 @@ msgstr "Αναρτήθηκε:" msgid "Posts for {month} {year}" msgstr "Αναρτήσεις για τον {month} του {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "Αναρτήσεις στις {day} {month}, {year}" + msgid "Nothing found." -msgstr "" +msgstr "Δε βρέθηκε περιεχόμενο" msgid "No posts found." -msgstr "" +msgstr "Δε βρέθηκαν αναρτήσεις" msgid "RSS feed" msgstr "" @@ -112,3 +118,18 @@ msgstr "" msgid "Skip to main content" msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/en.po b/translations/nikola.messages/en.po index ebd617c..7fdd725 100644 --- a/translations/nikola.messages/en.po +++ b/translations/nikola.messages/en.po @@ -5,15 +5,17 @@ # Translators: # Translators: # Translators: -# ralsina <ralsina@netmanagers.com.ar>, 2013 -# ralsina <ralsina@netmanagers.com.ar>, 2013 +# Translators: +# Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 +# Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-04-17 14:46+0000\n" -"Last-Translator: Kwpolska <kwpolska@gmail.com>\n" +"PO-Revision-Date: 2014-11-18 08:42+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" +"Language-Team: English (http://www.transifex.com/projects/p/nikola/language/en/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" @@ -23,6 +25,8 @@ msgstr "" msgid "More posts about %s" msgstr "More posts about %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "English" @@ -56,7 +60,7 @@ msgstr "page %d" msgid "Source" msgstr "Source" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Read in English" @@ -94,6 +98,9 @@ msgstr "Posted:" msgid "Posts for {month} {year}" msgstr "Posts for {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "Posts for {month} {day}, {year}" + msgid "Nothing found." msgstr "Nothing found." @@ -108,3 +115,18 @@ msgstr "%d min remaining to read" msgid "Skip to main content" msgstr "Skip to main content" + +msgid "Subcategories:" +msgstr "Subcategories:" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "(active)" + +#. Default content for a new post +msgid "Write your post here." +msgstr "Write your post here." + +#. Default content for a new page +msgid "Write your page here." +msgstr "Write your page here." diff --git a/translations/nikola.messages/eo.po b/translations/nikola.messages/eo.po index 2c7268b..291ce5c 100644 --- a/translations/nikola.messages/eo.po +++ b/translations/nikola.messages/eo.po @@ -6,6 +6,7 @@ # Translators: # Translators: # Translators: +# Translators: # David Paleino <d.paleino@gmail.com>, 2013 # David Paleino <d.paleino@gmail.com>, 2013 msgid "" @@ -13,7 +14,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Esperanto (http://www.transifex.com/projects/p/nikola/language/eo/)\n" "MIME-Version: 1.0\n" @@ -25,6 +26,8 @@ msgstr "" msgid "More posts about %s" msgstr "Pli artikoloj pri %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Anglalingve" @@ -58,7 +61,7 @@ msgstr "paĝo %d" msgid "Source" msgstr "Fonto" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Legu ĝin en Esperanto" @@ -96,6 +99,9 @@ msgstr "Skribita:" msgid "Posts for {month} {year}" msgstr "Artikoloj skribitaj en {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "" + msgid "Nothing found." msgstr "" @@ -110,3 +116,18 @@ msgstr "" msgid "Skip to main content" msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/es.po b/translations/nikola.messages/es.po index 5165fa0..3954a00 100644 --- a/translations/nikola.messages/es.po +++ b/translations/nikola.messages/es.po @@ -6,14 +6,17 @@ # Translators: # Translators: # Translators: +# Translators: +# Ángel García Cuartero <anhelido@gmail.com>, 2014-2015 +# Joaquín Tita <carpincho@gmail.com>, 2014 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 -# Roberto Alsina <ralsina@netmanagers.com.ar>, 2013-2014 +# Roberto Alsina <ralsina@netmanagers.com.ar>, 2013-2015 msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Spanish (http://www.transifex.com/projects/p/nikola/language/es/)\n" "MIME-Version: 1.0\n" @@ -23,19 +26,21 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n != 1);\n" msgid "More posts about %s" -msgstr "Más posts sobre %s" +msgstr "Más publicaciones sobre %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Español" msgid "Tags" -msgstr "Tags" +msgstr "Etiquetas" msgid "Categories" msgstr "Categorías" msgid "Tags and Categories" -msgstr "Tags y Categorías" +msgstr "Etiquetas y Categorías" msgid "Comments" msgstr "Comentarios" @@ -44,33 +49,33 @@ msgid "Read more" msgstr "Leer más" msgid "Posts about %s" -msgstr "Posts sobre %s" +msgstr "Publicaciones sobre %s" msgid "Next post" -msgstr "Siguiente post" +msgstr "Siguiente publicación" msgid "old posts, page %d" -msgstr "posts antiguos, página %d" +msgstr "publicaciones antiguas, página %d" msgid "page %d" msgstr "página %d" msgid "Source" -msgstr "Código" +msgstr "Código fuente" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Leer en español" msgid "Posts for year %s" -msgstr "Posts del año %s" +msgstr "Publicaciones del año %s" msgid "Newer posts" -msgstr "Posts posteriores" +msgstr "Publicaciones posteriores" msgid "Previous post" -msgstr "Post anterior" +msgstr "Publicación anterior" msgid "Also available in:" msgstr "También disponible en:" @@ -82,7 +87,7 @@ msgid "Original site" msgstr "Sitio original" msgid "Older posts" -msgstr "Posts anteriores" +msgstr "Publicaciones anteriores" msgid "Archive" msgstr "Archivo" @@ -96,17 +101,35 @@ msgstr "Publicado:" msgid "Posts for {month} {year}" msgstr "Posts de {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "Publicaciones de {day}, {month}, {year}" + msgid "Nothing found." -msgstr "No encontrado" +msgstr "No se encontró nada." msgid "No posts found." -msgstr "No se encontraron posts" +msgstr "No se encontraron publicaciones." msgid "RSS feed" -msgstr "feed RSS" +msgstr "Canal RSS" msgid "%d min remaining to read" -msgstr "restan %d minutos" +msgstr "quedan %d minutos de lectura" msgid "Skip to main content" +msgstr "Ir al contenido principal" + +msgid "Subcategories:" +msgstr "Subcategorías:" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "(activo)" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/et.po b/translations/nikola.messages/et.po index ee81b32..822722b 100644 --- a/translations/nikola.messages/et.po +++ b/translations/nikola.messages/et.po @@ -6,6 +6,7 @@ # Translators: # Translators: # Translators: +# Translators: # Chris Warrick <kwpolska@gmail.com>, 2014 # Chris Warrick <kwpolska@gmail.com>, 2014 # Lauri Võsandi <lauri.vosandi@gmail.com>, 2013 @@ -14,7 +15,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Estonian (http://www.transifex.com/projects/p/nikola/language/et/)\n" "MIME-Version: 1.0\n" @@ -26,6 +27,8 @@ msgstr "" msgid "More posts about %s" msgstr "Veel postitusi %s kohta" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Eesti" @@ -59,7 +62,7 @@ msgstr "leht %d" msgid "Source" msgstr "Lähtekood" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Loe eesti keeles" @@ -97,6 +100,9 @@ msgstr "Postitatud:" msgid "Posts for {month} {year}" msgstr "Postitused {year} aasta kuust {month} " +msgid "Posts for {month} {day}, {year}" +msgstr "" + msgid "Nothing found." msgstr "" @@ -111,3 +117,18 @@ msgstr "" msgid "Skip to main content" msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/eu.po b/translations/nikola.messages/eu.po index 03face8..2254d42 100644 --- a/translations/nikola.messages/eu.po +++ b/translations/nikola.messages/eu.po @@ -6,6 +6,7 @@ # Translators: # Translators: # Translators: +# Translators: # aitorp <aitorp@gmail.com>, 2013 # aitorp <aitorp@gmail.com>, 2013 msgid "" @@ -13,7 +14,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Basque (http://www.transifex.com/projects/p/nikola/language/eu/)\n" "MIME-Version: 1.0\n" @@ -25,6 +26,8 @@ msgstr "" msgid "More posts about %s" msgstr "%s-ri buruzko post gehiago" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Euskara" @@ -58,7 +61,7 @@ msgstr "orria %d" msgid "Source" msgstr "Iturria" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Euskaraz irakurri" @@ -96,6 +99,9 @@ msgstr "Argitaratuta:" msgid "Posts for {month} {year}" msgstr "{year}ko {month}ren postak" +msgid "Posts for {month} {day}, {year}" +msgstr "" + msgid "Nothing found." msgstr "" @@ -110,3 +116,18 @@ msgstr "" msgid "Skip to main content" msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/fa.po b/translations/nikola.messages/fa.po index 304d987..999640b 100644 --- a/translations/nikola.messages/fa.po +++ b/translations/nikola.messages/fa.po @@ -6,8 +6,9 @@ # Translators: # Translators: # Translators: +# Translators: # Hossein Raysehman <rayeshman@gmail.com>, 2014 -# Shahinism <ishahinism@gmail.com>, 2013 +# Shahinism <ishahinism@gmail.com>, 2013,2015 # Soroosh Azary Marhabi <soroosh@azary.ir>, 2013 # Shahinism <ishahinism@gmail.com>, 2013 # Soroosh Azary Marhabi <soroosh@azary.ir>, 2013 @@ -16,7 +17,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Persian (http://www.transifex.com/projects/p/nikola/language/fa/)\n" "MIME-Version: 1.0\n" @@ -28,6 +29,8 @@ msgstr "" msgid "More posts about %s" msgstr "ارسالهای بیشتر دربارهٔ%s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "فارسی" @@ -61,7 +64,7 @@ msgstr "برگه %d" msgid "Source" msgstr "منبع" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "به فارسی بخوانید" @@ -99,6 +102,9 @@ msgstr "ارسال شده:" msgid "Posts for {month} {year}" msgstr "ارسال برای {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "ارسال برای {month} {day}. {year}" + msgid "Nothing found." msgstr "هیچچیزی پیدا نشد." @@ -109,7 +115,22 @@ msgid "RSS feed" msgstr "خوراک" msgid "%d min remaining to read" -msgstr "" +msgstr "%d دقیقه برای خواندن باقی مانده" msgid "Skip to main content" +msgstr "متن اصلی را نادیده بگیر" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/fi.po b/translations/nikola.messages/fi.po index 721355e..6e46e51 100644 --- a/translations/nikola.messages/fi.po +++ b/translations/nikola.messages/fi.po @@ -6,6 +6,7 @@ # Translators: # Translators: # Translators: +# Translators: # ekari <eero.kari@gmail.com>, 2013 # ekari <eero.kari@gmail.com>, 2013-2014 msgid "" @@ -13,7 +14,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Finnish (http://www.transifex.com/projects/p/nikola/language/fi/)\n" "MIME-Version: 1.0\n" @@ -25,6 +26,8 @@ msgstr "" msgid "More posts about %s" msgstr "Lisää postauksia aiheesta %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Suomi" @@ -58,7 +61,7 @@ msgstr "sivu %d" msgid "Source" msgstr "Lähde" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Lue suomeksi" @@ -96,6 +99,9 @@ msgstr "Postattu:" msgid "Posts for {month} {year}" msgstr "Postauksia ajalle {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "" + msgid "Nothing found." msgstr "Ei hakutuloksia." @@ -106,7 +112,22 @@ msgid "RSS feed" msgstr "RSS syöte" msgid "%d min remaining to read" -msgstr "" +msgstr "%d minuuttia lukuaikaa" msgid "Skip to main content" +msgstr "Hyppää sisältöön" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/fil.po b/translations/nikola.messages/fil.po new file mode 100644 index 0000000..a8deecc --- /dev/null +++ b/translations/nikola.messages/fil.po @@ -0,0 +1,131 @@ +# Messages in Nikola +# Copyright (C) 2012-2013 +# This file is distributed under the same license as the Nikola package. +# +# Translators: +# Translators: +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: Nikola\n" +"Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" +"POT-Creation-Date: 2013-03-15 12:24-0300\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" +"Language-Team: Filipino (http://www.transifex.com/projects/p/nikola/language/fil/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: fil\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "More posts about %s" +msgstr "" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "LANGUAGE" +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "Categories" +msgstr "" + +msgid "Tags and Categories" +msgstr "" + +msgid "Comments" +msgstr "" + +msgid "Read more" +msgstr "" + +msgid "Posts about %s" +msgstr "" + +msgid "Next post" +msgstr "" + +msgid "old posts, page %d" +msgstr "" + +msgid "page %d" +msgstr "" + +msgid "Source" +msgstr "" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "Read in English" +msgstr "" + +msgid "Posts for year %s" +msgstr "" + +msgid "Newer posts" +msgstr "" + +msgid "Previous post" +msgstr "" + +msgid "Also available in:" +msgstr "" + +msgid "Languages:" +msgstr "" + +msgid "Original site" +msgstr "" + +msgid "Older posts" +msgstr "" + +msgid "Archive" +msgstr "" + +msgid "Publication date" +msgstr "" + +msgid "Posted:" +msgstr "" + +msgid "Posts for {month} {year}" +msgstr "" + +msgid "Posts for {month} {day}, {year}" +msgstr "" + +msgid "Nothing found." +msgstr "" + +msgid "No posts found." +msgstr "" + +msgid "RSS feed" +msgstr "" + +msgid "%d min remaining to read" +msgstr "" + +msgid "Skip to main content" +msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/fr.po b/translations/nikola.messages/fr.po index fd5affa..7232a16 100644 --- a/translations/nikola.messages/fr.po +++ b/translations/nikola.messages/fr.po @@ -6,9 +6,10 @@ # Translators: # Translators: # Translators: +# Translators: # John Mille <john.mille78@gmail.com>, 2014 # John Mille <john.mille78@gmail.com>, 2014 -# Pablo SEMINARIO <pablo@seminar.io>, 2014 +# Pablo SEMINARIO <pablo@seminar.io>, 2014-2015 # Pablo SEMINARIO <pablo@seminar.io>, 2013 # Pablo SEMINARIO <pablo@seminar.io>, 2013 # Pablo SEMINARIO <pablo@seminar.io>, 2013 @@ -19,8 +20,8 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-08-03 16:31+0000\n" -"Last-Translator: Pablo SEMINARIO <pablo@seminar.io>\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: French (http://www.transifex.com/projects/p/nikola/language/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -31,6 +32,8 @@ msgstr "" msgid "More posts about %s" msgstr "Plus d'articles sur %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Français" @@ -64,7 +67,7 @@ msgstr "page %d" msgid "Source" msgstr "Source" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Lire en français" @@ -73,13 +76,13 @@ msgid "Posts for year %s" msgstr "Articles de l'année %s" msgid "Newer posts" -msgstr "Billets récents" +msgstr "Articles récents" msgid "Previous post" msgstr "Article précédent" msgid "Also available in:" -msgstr "Egalement disponible en:" +msgstr "Également disponible en:" msgid "Languages:" msgstr "Langues:" @@ -102,11 +105,14 @@ msgstr "Publié:" msgid "Posts for {month} {year}" msgstr "Articles de {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "Articles du {day} {month} {year}" + msgid "Nothing found." msgstr "Pas de résultats." msgid "No posts found." -msgstr "Pas de billets." +msgstr "Pas d'articles." msgid "RSS feed" msgstr "Flux RSS" @@ -116,3 +122,18 @@ msgstr "Il reste encore %d min. de lecture" msgid "Skip to main content" msgstr "Aller au contenu principal" + +msgid "Subcategories:" +msgstr "Sous-catégories" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "(actif)" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/gl.po b/translations/nikola.messages/gl.po index bc3e392..5af830f 100644 --- a/translations/nikola.messages/gl.po +++ b/translations/nikola.messages/gl.po @@ -6,12 +6,13 @@ # Translators: # Translators: # Translators: +# Translators: msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Galician (http://www.transifex.com/projects/p/nikola/language/gl/)\n" "MIME-Version: 1.0\n" @@ -23,6 +24,8 @@ msgstr "" msgid "More posts about %s" msgstr "" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "" @@ -56,7 +59,7 @@ msgstr "" msgid "Source" msgstr "" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "" @@ -94,6 +97,9 @@ msgstr "" msgid "Posts for {month} {year}" msgstr "" +msgid "Posts for {month} {day}, {year}" +msgstr "" + msgid "Nothing found." msgstr "" @@ -108,3 +114,18 @@ msgstr "" msgid "Skip to main content" msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/hi.po b/translations/nikola.messages/hi.po index 32de7f3..a2967f2 100644 --- a/translations/nikola.messages/hi.po +++ b/translations/nikola.messages/hi.po @@ -6,13 +6,14 @@ # Translators: # Translators: # Translators: -# seanpue <a@seanpue.com>, 2014 +# Translators: +# seanpue <a@seanpue.com>, 2014-2015 msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Hindi (http://www.transifex.com/projects/p/nikola/language/hi/)\n" "MIME-Version: 1.0\n" @@ -24,6 +25,8 @@ msgstr "" msgid "More posts about %s" msgstr "%s के बारे में अौर पोस्टें" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "हिन्दी" @@ -37,7 +40,7 @@ msgid "Tags and Categories" msgstr "टैग्स और श्रेणियाँ" msgid "Comments" -msgstr "" +msgstr "टिप्पणियाँ" msgid "Read more" msgstr "और पढ़िए" @@ -57,7 +60,7 @@ msgstr "पृष्ठ %d" msgid "Source" msgstr "सोर्स" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "हिन्दी में पढ़िए" @@ -75,7 +78,7 @@ msgid "Also available in:" msgstr "उपलब्ध भाषाएँ:" msgid "Languages:" -msgstr "" +msgstr "भाषाएँ:" msgid "Original site" msgstr "असली साइट" @@ -87,7 +90,7 @@ msgid "Archive" msgstr "आर्काइव" msgid "Publication date" -msgstr "" +msgstr "प्रकाशन की तारीख" msgid "Posted:" msgstr "पोस्टेड:" @@ -95,17 +98,35 @@ msgstr "पोस्टेड:" msgid "Posts for {month} {year}" msgstr "{month} {year} की पोस्टें" +msgid "Posts for {month} {day}, {year}" +msgstr "{day} {month} {year} की पोस्टें" + msgid "Nothing found." -msgstr "" +msgstr "कुछ नहीं मिल सका" msgid "No posts found." -msgstr "" +msgstr "कोई पोस्ट नहीं मिल सकी" msgid "RSS feed" -msgstr "" +msgstr "आर एस एस फ़ीड" msgid "%d min remaining to read" -msgstr "" +msgstr "पढ़ने में %d मिनट बाकी" msgid "Skip to main content" +msgstr "मुख्य सामग्री पर जाएँ" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/hr.po b/translations/nikola.messages/hr.po index a528042..0135634 100644 --- a/translations/nikola.messages/hr.po +++ b/translations/nikola.messages/hr.po @@ -6,6 +6,7 @@ # Translators: # Translators: # Translators: +# Translators: # tty, 2013 # tty, 2013-2014 msgid "" @@ -13,7 +14,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Croatian (http://www.transifex.com/projects/p/nikola/language/hr/)\n" "MIME-Version: 1.0\n" @@ -25,6 +26,8 @@ msgstr "" msgid "More posts about %s" msgstr "Više postova o %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "hrvatski" @@ -58,7 +61,7 @@ msgstr "stranice %d" msgid "Source" msgstr "Izvor" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Čitaj na hrvatskom" @@ -96,6 +99,9 @@ msgstr "Objavljeno:" msgid "Posts for {month} {year}" msgstr "Postovi za {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "" + msgid "Nothing found." msgstr "Nema ničeg." @@ -110,3 +116,18 @@ msgstr "" msgid "Skip to main content" msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/id.po b/translations/nikola.messages/id.po new file mode 100644 index 0000000..840d064 --- /dev/null +++ b/translations/nikola.messages/id.po @@ -0,0 +1,132 @@ +# Messages in Nikola +# Copyright (C) 2012-2013 +# This file is distributed under the same license as the Nikola package. +# +# Translators: +# Translators: +# Translators: +# Translators: +# Translators: +# Willy Sudiarto Raharjo <willysr@slackware-id.org>, 2014-2015 +msgid "" +msgstr "" +"Project-Id-Version: Nikola\n" +"Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" +"POT-Creation-Date: 2013-03-15 12:24-0300\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" +"Language-Team: Indonesian (http://www.transifex.com/projects/p/nikola/language/id/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: id\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "More posts about %s" +msgstr "Lebih banyak tulisan tentang %s" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "LANGUAGE" +msgstr "Inggris" + +msgid "Tags" +msgstr "Tag" + +msgid "Categories" +msgstr "Kategori" + +msgid "Tags and Categories" +msgstr "Tag dan Kategori" + +msgid "Comments" +msgstr "Komentar" + +msgid "Read more" +msgstr "Baca selengkapnya" + +msgid "Posts about %s" +msgstr "Tulisan tentang %s" + +msgid "Next post" +msgstr "Tulisan berikutnya" + +msgid "old posts, page %d" +msgstr "tulisan lama, halaman %d" + +msgid "page %d" +msgstr "halaman %d" + +msgid "Source" +msgstr "Sumber" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "Read in English" +msgstr "Baca dalam bahasa Inggris" + +msgid "Posts for year %s" +msgstr "Tulisan untuk tahun %s" + +msgid "Newer posts" +msgstr "Tulisan lebih baru" + +msgid "Previous post" +msgstr "Tulisan sebelumnya" + +msgid "Also available in:" +msgstr "Juga tersedia dalam:" + +msgid "Languages:" +msgstr "Bahasa:" + +msgid "Original site" +msgstr "Situs orisinal" + +msgid "Older posts" +msgstr "Tulisan lebih lama" + +msgid "Archive" +msgstr "Arsip" + +msgid "Publication date" +msgstr "Tanggal publikasi" + +msgid "Posted:" +msgstr "Ditulis oleh:" + +msgid "Posts for {month} {year}" +msgstr "Tulisan untuk {month} {year}" + +msgid "Posts for {month} {day}, {year}" +msgstr "Tulisan untuk {month} {day}, {year}" + +msgid "Nothing found." +msgstr "Tidak ditemukan." + +msgid "No posts found." +msgstr "Tidak ada tulisan yang ditemukan." + +msgid "RSS feed" +msgstr "Sindikasi RSS" + +msgid "%d min remaining to read" +msgstr "%d menit tersisa untuk membaca" + +msgid "Skip to main content" +msgstr "Lanjutkan ke konten utama" + +msgid "Subcategories:" +msgstr "Sub kategori:" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "(aktif)" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/it.po b/translations/nikola.messages/it.po index 9964c98..3d76538 100644 --- a/translations/nikola.messages/it.po +++ b/translations/nikola.messages/it.po @@ -6,9 +6,11 @@ # Translators: # Translators: # Translators: +# Translators: # Alessandro Pisa <alessandro.pisa@gmail.com>, 2013 # Chris Warrick <kwpolska@gmail.com>, 2014 # David Paleino <d.paleino@gmail.com>, 2013 +# Nicola Larosa <transifex@teknico.net>, 2015 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 # Stefano Karapetsas <stefano@karapetsas.com>, 2014 @@ -17,8 +19,8 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" -"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" +"PO-Revision-Date: 2015-06-24 12:31+0000\n" +"Last-Translator: Nicola Larosa <transifex@teknico.net>\n" "Language-Team: Italian (http://www.transifex.com/projects/p/nikola/language/it/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -29,17 +31,19 @@ msgstr "" msgid "More posts about %s" msgstr "Altri articoli collegati %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" -msgstr "Italiano" +msgstr "Inglese" msgid "Tags" -msgstr "Tags" +msgstr "Tag" msgid "Categories" msgstr "Categorie" msgid "Tags and Categories" -msgstr "Tags e Categorie" +msgstr "Tag e Categorie" msgid "Comments" msgstr "Commenti" @@ -54,7 +58,7 @@ msgid "Next post" msgstr "Articolo successivo" msgid "old posts, page %d" -msgstr "pagina dei vecchi articoli %d" +msgstr "vecchi articoli, pagina %d" msgid "page %d" msgstr "pagina %d" @@ -62,22 +66,22 @@ msgstr "pagina %d" msgid "Source" msgstr "Sorgente" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" -msgstr "Leggi in italiano" +msgstr "Leggi in inglese" msgid "Posts for year %s" msgstr "Articoli per l'anno %s" msgid "Newer posts" -msgstr "Articoli recenti" +msgstr "Articoli più recenti" msgid "Previous post" msgstr "Articolo precedente" msgid "Also available in:" -msgstr "Anche disponibile in:" +msgstr "Disponibile anche in:" msgid "Languages:" msgstr "Lingue:" @@ -100,6 +104,9 @@ msgstr "Pubblicato:" msgid "Posts for {month} {year}" msgstr "Articoli per {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "Articoli per il {day} {month} {year}" + msgid "Nothing found." msgstr "Non trovato." @@ -107,10 +114,25 @@ msgid "No posts found." msgstr "Nessun articolo trovato." msgid "RSS feed" -msgstr "Flusso RSS" +msgstr "Feed RSS" msgid "%d min remaining to read" -msgstr "ancora %d minuti" +msgstr "ulteriori %d minuti di lettura" msgid "Skip to main content" -msgstr "" +msgstr "Vai al testo principale" + +msgid "Subcategories:" +msgstr "Sottocategorie:" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "(attivo)" + +#. Default content for a new post +msgid "Write your post here." +msgstr "Scrivi qui il tuo post." + +#. Default content for a new page +msgid "Write your page here." +msgstr "Scrivi qui la tua pagina." diff --git a/translations/nikola.messages/ja.po b/translations/nikola.messages/ja.po index 675af24..3edd297 100644 --- a/translations/nikola.messages/ja.po +++ b/translations/nikola.messages/ja.po @@ -6,9 +6,10 @@ # Translators: # Translators: # Translators: +# Translators: # Chris Warrick <kwpolska@gmail.com>, 2013 # Chris Warrick <kwpolska@gmail.com>, 2013 -# Mika Kobayashi, 2014 +# Mika Kobayashi, 2014-2015 # Yasuhiko Shiga <4wordextinguisher@gmail.com>, 2013 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 @@ -18,7 +19,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Japanese (http://www.transifex.com/projects/p/nikola/language/ja/)\n" "MIME-Version: 1.0\n" @@ -30,6 +31,8 @@ msgstr "" msgid "More posts about %s" msgstr "タグ: %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "日本語" @@ -63,7 +66,7 @@ msgstr "ページ %d" msgid "Source" msgstr "ソース" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "日本語で読む" @@ -101,6 +104,9 @@ msgstr "投稿日時:" msgid "Posts for {month} {year}" msgstr "{year}年{month}月の記事" +msgid "Posts for {month} {day}, {year}" +msgstr "{year}年{month}月{day}日の記事" + msgid "Nothing found." msgstr "なにも見つかりませんでした" @@ -111,7 +117,22 @@ msgid "RSS feed" msgstr "RSS フィード" msgid "%d min remaining to read" -msgstr "" +msgstr "読込むまで残り %d 分" msgid "Skip to main content" +msgstr "メインコンテンツをスキップ" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/ko.po b/translations/nikola.messages/ko.po new file mode 100644 index 0000000..23d886a --- /dev/null +++ b/translations/nikola.messages/ko.po @@ -0,0 +1,132 @@ +# Messages in Nikola +# Copyright (C) 2012-2013 +# This file is distributed under the same license as the Nikola package. +# +# Translators: +# Translators: +# Translators: +# Translators: +# Translators: +# Dong Geun <dglee2@gmail.com>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: Nikola\n" +"Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" +"POT-Creation-Date: 2013-03-15 12:24-0300\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" +"Language-Team: Korean (http://www.transifex.com/projects/p/nikola/language/ko/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ko\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "More posts about %s" +msgstr "%s에 대한 또다른 포스트" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "LANGUAGE" +msgstr "영어" + +msgid "Tags" +msgstr "태그" + +msgid "Categories" +msgstr "분류" + +msgid "Tags and Categories" +msgstr "태그와 분류" + +msgid "Comments" +msgstr "댓글" + +msgid "Read more" +msgstr "더 읽기" + +msgid "Posts about %s" +msgstr "%s에 대한 포스트" + +msgid "Next post" +msgstr "다음 포스트" + +msgid "old posts, page %d" +msgstr "이전 포스트, 페이지 %d" + +msgid "page %d" +msgstr "페이지 %d" + +msgid "Source" +msgstr "원문" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "Read in English" +msgstr "영어로 읽기" + +msgid "Posts for year %s" +msgstr "%s년도 포스트" + +msgid "Newer posts" +msgstr "최신 포스트" + +msgid "Previous post" +msgstr "이전 포스트" + +msgid "Also available in:" +msgstr "" + +msgid "Languages:" +msgstr "언어:" + +msgid "Original site" +msgstr "출처" + +msgid "Older posts" +msgstr "옛날 포스트" + +msgid "Archive" +msgstr "저장소" + +msgid "Publication date" +msgstr "발간일" + +msgid "Posted:" +msgstr "" + +msgid "Posts for {month} {year}" +msgstr "{year}년 {month}월에 쓴 포스트" + +msgid "Posts for {month} {day}, {year}" +msgstr "" + +msgid "Nothing found." +msgstr "검색 결과 없음." + +msgid "No posts found." +msgstr "검색된 포스트 없음." + +msgid "RSS feed" +msgstr "RSS 목록" + +msgid "%d min remaining to read" +msgstr "읽기 %d분 남음." + +msgid "Skip to main content" +msgstr "주 콘텐츠로 바로가기" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/nb.po b/translations/nikola.messages/nb.po index fea46d5..57ad442 100644 --- a/translations/nikola.messages/nb.po +++ b/translations/nikola.messages/nb.po @@ -6,13 +6,14 @@ # Translators: # Translators: # Translators: +# Translators: # Daniel <i18n@daniel.priv.no>, 2013 msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Norwegian Bokmål (http://www.transifex.com/projects/p/nikola/language/nb/)\n" "MIME-Version: 1.0\n" @@ -24,6 +25,8 @@ msgstr "" msgid "More posts about %s" msgstr "Flere innlegg om %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "norsk" @@ -57,7 +60,7 @@ msgstr "side %d" msgid "Source" msgstr "Kilde" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Les på norsk" @@ -95,6 +98,9 @@ msgstr "Publisert:" msgid "Posts for {month} {year}" msgstr "Innlegg fra {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "" + msgid "Nothing found." msgstr "" @@ -109,3 +115,18 @@ msgstr "" msgid "Skip to main content" msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/nl.po b/translations/nikola.messages/nl.po index a1ad585..c83fede 100644 --- a/translations/nikola.messages/nl.po +++ b/translations/nikola.messages/nl.po @@ -6,15 +6,16 @@ # Translators: # Translators: # Translators: +# Translators: # Joes Staal <joes@staalkemade.net>, 2013 -# Joes Staal <joes@staalkemade.net>, 2013-2014 +# Joes Staal <joes@staalkemade.net>, 2013-2015 msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-08-01 11:19+0000\n" -"Last-Translator: Joes Staal <joes@staalkemade.net>\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Dutch (http://www.transifex.com/projects/p/nikola/language/nl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -25,6 +26,8 @@ msgstr "" msgid "More posts about %s" msgstr "Meer berichten over %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Nederlands" @@ -58,7 +61,7 @@ msgstr "pagina %d" msgid "Source" msgstr "Bron" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Lees in het Nederlands" @@ -96,6 +99,9 @@ msgstr "Geplaatst:" msgid "Posts for {month} {year}" msgstr "Berichten voor {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "Berichten voor {month} {day}, {year}" + msgid "Nothing found." msgstr "Niets gevonden." @@ -110,3 +116,18 @@ msgstr "%d min resterende leestijd " msgid "Skip to main content" msgstr "Ga door naar de hoofdinhoud" + +msgid "Subcategories:" +msgstr "Subcategorieën" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "(actief)" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/pl.po b/translations/nikola.messages/pl.po index f339b23..3859636 100644 --- a/translations/nikola.messages/pl.po +++ b/translations/nikola.messages/pl.po @@ -6,7 +6,8 @@ # Translators: # Translators: # Translators: -# Chris Warrick <kwpolska@gmail.com>, 2013-2014 +# Translators: +# Chris Warrick <kwpolska@gmail.com>, 2013-2015 # Chris Warrick <kwpolska@gmail.com>, 2013 # Chris Warrick <kwpolska@gmail.com>, 2013 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 @@ -16,7 +17,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:41+0000\n" +"PO-Revision-Date: 2015-06-24 12:13+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Polish (http://www.transifex.com/projects/p/nikola/language/pl/)\n" "MIME-Version: 1.0\n" @@ -28,6 +29,8 @@ msgstr "" msgid "More posts about %s" msgstr "Więcej postów o %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Polski" @@ -61,7 +64,7 @@ msgstr "strona %d" msgid "Source" msgstr "Źródło" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Czytaj po polsku" @@ -99,6 +102,9 @@ msgstr "Opublikowano:" msgid "Posts for {month} {year}" msgstr "Posty z {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "Posty z {day} {month} {year}" + msgid "Nothing found." msgstr "Nic nie znaleziono." @@ -113,3 +119,18 @@ msgstr "zostało %d minut czytania" msgid "Skip to main content" msgstr "Przejdź do treści" + +msgid "Subcategories:" +msgstr "Podkategorie:" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "(aktywne)" + +#. Default content for a new post +msgid "Write your post here." +msgstr "Tu wpisz treść postu." + +#. Default content for a new page +msgid "Write your page here." +msgstr "Tu wpisz treść strony." diff --git a/translations/nikola.messages/pt.po b/translations/nikola.messages/pt.po index 686661f..89f803f 100644 --- a/translations/nikola.messages/pt.po +++ b/translations/nikola.messages/pt.po @@ -6,12 +6,13 @@ # Translators: # Translators: # Translators: +# Translators: msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Portuguese (http://www.transifex.com/projects/p/nikola/language/pt/)\n" "MIME-Version: 1.0\n" @@ -23,6 +24,8 @@ msgstr "" msgid "More posts about %s" msgstr "" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "" @@ -56,7 +59,7 @@ msgstr "" msgid "Source" msgstr "" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "" @@ -94,6 +97,9 @@ msgstr "" msgid "Posts for {month} {year}" msgstr "" +msgid "Posts for {month} {day}, {year}" +msgstr "" + msgid "Nothing found." msgstr "" @@ -108,3 +114,18 @@ msgstr "" msgid "Skip to main content" msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/pt_BR.po b/translations/nikola.messages/pt_BR.po index d145399..d3e6d5c 100644 --- a/translations/nikola.messages/pt_BR.po +++ b/translations/nikola.messages/pt_BR.po @@ -6,8 +6,10 @@ # Translators: # Translators: # Translators: -# Thiago Cangussu <cangussu.thg@gmail.com>, 2014 +# Translators: +# Thiago Cangussu <cng.thg@gmail.com>, 2014 # eduardo <schettino72@gmail.com>, 2013 +# felipeiasi <felipeiasi@gmail.com>, 2015 # Chris Warrick <kwpolska@gmail.com>, 2013 # Chris Warrick <kwpolska@gmail.com>, 2013 # Roberto Alsina <ralsina@netmanagers.com.ar>, 2013 @@ -18,7 +20,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/nikola/language/pt_BR/)\n" "MIME-Version: 1.0\n" @@ -30,6 +32,8 @@ msgstr "" msgid "More posts about %s" msgstr "Mais posts sobre %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Português" @@ -63,7 +67,7 @@ msgstr "página %d" msgid "Source" msgstr "Código" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Ler em português" @@ -101,6 +105,9 @@ msgstr "Publicado:" msgid "Posts for {month} {year}" msgstr "Posts de {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "Posts do {day} {month}, {year}" + msgid "Nothing found." msgstr "Nada encontrado." @@ -114,4 +121,19 @@ msgid "%d min remaining to read" msgstr "%d mín restante para leitura" msgid "Skip to main content" +msgstr "Pular para o conteúdo principal" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/ru.po b/translations/nikola.messages/ru.po index 2d5ba28..6678646 100644 --- a/translations/nikola.messages/ru.po +++ b/translations/nikola.messages/ru.po @@ -6,6 +6,7 @@ # Translators: # Translators: # Translators: +# Translators: # Dmitry Verkhoturov <paskal.07@gmail.com>, 2014 # Max Arnold <lwarxx@gmail.com>, 2013 # Max Arnold <lwarxx@gmail.com>, 2013 @@ -16,18 +17,20 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Russian (http://www.transifex.com/projects/p/nikola/language/ru/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: ru\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" +"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n" msgid "More posts about %s" msgstr "Больше записей о %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Русский" @@ -61,7 +64,7 @@ msgstr "%d страница" msgid "Source" msgstr "Источник" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Прочесть по-русски" @@ -99,6 +102,9 @@ msgstr "Опубликовано:" msgid "Posts for {month} {year}" msgstr "Записи за {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "" + msgid "Nothing found." msgstr "Ничего не найдено." @@ -112,4 +118,19 @@ msgid "%d min remaining to read" msgstr "%d минут чтения осталось" msgid "Skip to main content" +msgstr "Перейти к главному содержимому" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/si_LK.po b/translations/nikola.messages/si_LK.po index f56b6e2..49a4976 100644 --- a/translations/nikola.messages/si_LK.po +++ b/translations/nikola.messages/si_LK.po @@ -6,12 +6,13 @@ # Translators: # Translators: # Translators: +# Translators: msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Sinhala (Sri Lanka) (http://www.transifex.com/projects/p/nikola/language/si_LK/)\n" "MIME-Version: 1.0\n" @@ -23,6 +24,8 @@ msgstr "" msgid "More posts about %s" msgstr "" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "" @@ -56,7 +59,7 @@ msgstr "" msgid "Source" msgstr "" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "" @@ -94,6 +97,9 @@ msgstr "" msgid "Posts for {month} {year}" msgstr "" +msgid "Posts for {month} {day}, {year}" +msgstr "" + msgid "Nothing found." msgstr "" @@ -108,3 +114,18 @@ msgstr "" msgid "Skip to main content" msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/sk.po b/translations/nikola.messages/sk.po index 3584a27..cf10280 100644 --- a/translations/nikola.messages/sk.po +++ b/translations/nikola.messages/sk.po @@ -6,13 +6,15 @@ # Translators: # Translators: # Translators: +# Translators: # bs_ <info@pwn.sk>, 2014 +# Michal Petrucha <michal.petrucha@ksp.sk>, 2014 msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Slovak (http://www.transifex.com/projects/p/nikola/language/sk/)\n" "MIME-Version: 1.0\n" @@ -24,6 +26,8 @@ msgstr "" msgid "More posts about %s" msgstr "Viac príspevkov o %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Slovenčina" @@ -57,7 +61,7 @@ msgstr "stránka %d" msgid "Source" msgstr "Zdroj" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Čítať v slovenčine" @@ -95,6 +99,9 @@ msgstr "Zverejnené:" msgid "Posts for {month} {year}" msgstr "Príspevky za mesiac {month} z roku {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "Príspevky z dňa {day}. {month} {year}" + msgid "Nothing found." msgstr "Nič nenájdené." @@ -108,4 +115,19 @@ msgid "%d min remaining to read" msgstr "zostáva %d minút na čítanie" msgid "Skip to main content" +msgstr "Skočiť na hlavný obsah" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/sl.po b/translations/nikola.messages/sl.po index 7f3932d..ccb78c8 100644 --- a/translations/nikola.messages/sl.po +++ b/translations/nikola.messages/sl.po @@ -6,15 +6,16 @@ # Translators: # Translators: # Translators: +# Translators: # vezjakv <vezjakv@gmail.com>, 2013 -# vezjakv <vezjakv@gmail.com>, 2013-2014 +# vezjakv <vezjakv@gmail.com>, 2013-2015 msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:50+0000\n" -"Last-Translator: vezjakv <vezjakv@gmail.com>\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Slovenian (http://www.transifex.com/projects/p/nikola/language/sl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -25,6 +26,8 @@ msgstr "" msgid "More posts about %s" msgstr "Več objav o %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Slovenščina" @@ -58,7 +61,7 @@ msgstr "stran %d" msgid "Source" msgstr "Izvor" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Beri v slovenščini" @@ -96,6 +99,9 @@ msgstr "Objavljeno:" msgid "Posts for {month} {year}" msgstr "Objave za {month} {year}" +msgid "Posts for {month} {day}, {year}" +msgstr "Objave za {day}. {month}, {year}" + msgid "Nothing found." msgstr "Brez zadetkov." @@ -110,3 +116,18 @@ msgstr "še %d min za branje preostanka" msgid "Skip to main content" msgstr "Preskoči na glavno vsebino" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/sr.po b/translations/nikola.messages/sr.po new file mode 100644 index 0000000..6a335a9 --- /dev/null +++ b/translations/nikola.messages/sr.po @@ -0,0 +1,132 @@ +# Messages in Nikola +# Copyright (C) 2012-2013 +# This file is distributed under the same license as the Nikola package. +# +# Translators: +# Translators: +# Translators: +# Translators: +# Translators: +# Ivan Radeljic <radeljicivan85@gmail.com>, 2014 +msgid "" +msgstr "" +"Project-Id-Version: Nikola\n" +"Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" +"POT-Creation-Date: 2013-03-15 12:24-0300\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" +"Language-Team: Serbian (http://www.transifex.com/projects/p/nikola/language/sr/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sr\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "More posts about %s" +msgstr "Више постова о %s" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "LANGUAGE" +msgstr "Српски" + +msgid "Tags" +msgstr "Тагови" + +msgid "Categories" +msgstr "Категорије" + +msgid "Tags and Categories" +msgstr "Тагови и категорије" + +msgid "Comments" +msgstr "Коментари" + +msgid "Read more" +msgstr "Прочитај више" + +msgid "Posts about %s" +msgstr "Постови о %s" + +msgid "Next post" +msgstr "Следећи пост" + +msgid "old posts, page %d" +msgstr "стари постови, страна %d" + +msgid "page %d" +msgstr "страна %d" + +msgid "Source" +msgstr "Извор" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "Read in English" +msgstr "Прочитај на српском" + +msgid "Posts for year %s" +msgstr "Постови за годину %s" + +msgid "Newer posts" +msgstr "Новији постови" + +msgid "Previous post" +msgstr "Претходни пост" + +msgid "Also available in:" +msgstr "Такође доступан у:" + +msgid "Languages:" +msgstr "Језици:" + +msgid "Original site" +msgstr "Оригинал сајт" + +msgid "Older posts" +msgstr "Старији постови" + +msgid "Archive" +msgstr "Архива" + +msgid "Publication date" +msgstr "Датум објаве" + +msgid "Posted:" +msgstr "Објављено:" + +msgid "Posts for {month} {year}" +msgstr "Постови за {month} {year}" + +msgid "Posts for {month} {day}, {year}" +msgstr "" + +msgid "Nothing found." +msgstr "Није ништа пронађено." + +msgid "No posts found." +msgstr "Нема постова." + +msgid "RSS feed" +msgstr "RSS feed" + +msgid "%d min remaining to read" +msgstr "%d минута је преостало за читање" + +msgid "Skip to main content" +msgstr "Прескочи на главни садржај" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/sv.po b/translations/nikola.messages/sv.po new file mode 100644 index 0000000..07cc478 --- /dev/null +++ b/translations/nikola.messages/sv.po @@ -0,0 +1,134 @@ +# Messages in Nikola +# Copyright (C) 2012-2013 +# This file is distributed under the same license as the Nikola package. +# +# Translators: +# Translators: +# Translators: +# Translators: +# Translators: +# Chris Warrick <kwpolska@gmail.com>, 2014 +# Johan Sommerfeld <johan@s2hc.com>, 2014 +# Markus Edemalm <markus@edemalm.se>, 2015 +msgid "" +msgstr "" +"Project-Id-Version: Nikola\n" +"Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" +"POT-Creation-Date: 2013-03-15 12:24-0300\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" +"Language-Team: Swedish (http://www.transifex.com/projects/p/nikola/language/sv/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: sv\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "More posts about %s" +msgstr "Mer inlägg om %s" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "LANGUAGE" +msgstr "Svenska" + +msgid "Tags" +msgstr "Taggar" + +msgid "Categories" +msgstr "Kategorier" + +msgid "Tags and Categories" +msgstr "Taggar och Kategorier" + +msgid "Comments" +msgstr "Kommentarer" + +msgid "Read more" +msgstr "Läs mer" + +msgid "Posts about %s" +msgstr "Inlägg om %s" + +msgid "Next post" +msgstr "Nästa inlägg" + +msgid "old posts, page %d" +msgstr "gamla inlägg, sida %d" + +msgid "page %d" +msgstr "sida %d" + +msgid "Source" +msgstr "Källa" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "Read in English" +msgstr "Läs på Svenska" + +msgid "Posts for year %s" +msgstr "Inlägg för år %s" + +msgid "Newer posts" +msgstr "Nya inlägg" + +msgid "Previous post" +msgstr "Föregående inlägg" + +msgid "Also available in:" +msgstr "Även tillgänglig på:" + +msgid "Languages:" +msgstr "Språk:" + +msgid "Original site" +msgstr "Orgnialsida" + +msgid "Older posts" +msgstr "Äldre inlägg" + +msgid "Archive" +msgstr "Arkiv" + +msgid "Publication date" +msgstr "Publiceringsdatum" + +msgid "Posted:" +msgstr "Publicerad" + +msgid "Posts for {month} {year}" +msgstr "Inlägg för {month} {year}" + +msgid "Posts for {month} {day}, {year}" +msgstr "Inlägg för {month} {day}, {year}" + +msgid "Nothing found." +msgstr "Inget hittat" + +msgid "No posts found." +msgstr "Inga inlägg hittade" + +msgid "RSS feed" +msgstr "RSS flöde" + +msgid "%d min remaining to read" +msgstr "%d minuter kvar att läsa" + +msgid "Skip to main content" +msgstr "hoppa till huvudinehåll" + +msgid "Subcategories:" +msgstr "Underkategorier:" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/tl.po b/translations/nikola.messages/tl.po new file mode 100644 index 0000000..b3cae1e --- /dev/null +++ b/translations/nikola.messages/tl.po @@ -0,0 +1,132 @@ +# Messages in Nikola +# Copyright (C) 2012-2013 +# This file is distributed under the same license as the Nikola package. +# +# Translators: +# Translators: +# Translators: +# Translators: +# Translators: +# Ben Hearsum <bhearsum@gmail.com>, 2015 +msgid "" +msgstr "" +"Project-Id-Version: Nikola\n" +"Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" +"POT-Creation-Date: 2013-03-15 12:24-0300\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" +"Language-Team: Tagalog (http://www.transifex.com/projects/p/nikola/language/tl/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: tl\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "More posts about %s" +msgstr "" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "LANGUAGE" +msgstr "Ingles" + +msgid "Tags" +msgstr "Mga Tag" + +msgid "Categories" +msgstr "" + +msgid "Tags and Categories" +msgstr "" + +msgid "Comments" +msgstr "" + +msgid "Read more" +msgstr "" + +msgid "Posts about %s" +msgstr "" + +msgid "Next post" +msgstr "Susunod" + +msgid "old posts, page %d" +msgstr "" + +msgid "page %d" +msgstr "" + +msgid "Source" +msgstr "" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "Read in English" +msgstr "" + +msgid "Posts for year %s" +msgstr "" + +msgid "Newer posts" +msgstr "" + +msgid "Previous post" +msgstr "" + +msgid "Also available in:" +msgstr "" + +msgid "Languages:" +msgstr "Mga Wika:" + +msgid "Original site" +msgstr "" + +msgid "Older posts" +msgstr "" + +msgid "Archive" +msgstr "" + +msgid "Publication date" +msgstr "" + +msgid "Posted:" +msgstr "" + +msgid "Posts for {month} {year}" +msgstr "" + +msgid "Posts for {month} {day}, {year}" +msgstr "" + +msgid "Nothing found." +msgstr "" + +msgid "No posts found." +msgstr "" + +msgid "RSS feed" +msgstr "" + +msgid "%d min remaining to read" +msgstr "" + +msgid "Skip to main content" +msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/tr.po b/translations/nikola.messages/tr.po index 0372bcd..0e4ca77 100644 --- a/translations/nikola.messages/tr.po +++ b/translations/nikola.messages/tr.po @@ -6,15 +6,16 @@ # Translators: # Translators: # Translators: -# Batuhan Büyükgüzel <bbuyukguzel@gmail.com>, 2013-2014 -# Caner Başaran <basaran.caner@gmail.com>, 2014 +# Translators: +# Batuhan Büyükgüzel <bbuyukguzel@gmail.com>, 2013-2015 +# Caner Başaran <basaran.caner@gmail.com>, 2013-2014 # Caner Başaran <basaran.caner@gmail.com>, 2013 msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Turkish (http://www.transifex.com/projects/p/nikola/language/tr/)\n" "MIME-Version: 1.0\n" @@ -26,6 +27,8 @@ msgstr "" msgid "More posts about %s" msgstr "%s ilgili diğer yazılar" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "Türkçe" @@ -59,7 +62,7 @@ msgstr "sayfa %d" msgid "Source" msgstr "Kaynak" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "Türkçe olarak oku" @@ -97,6 +100,9 @@ msgstr "Yayın tarihi:" msgid "Posts for {month} {year}" msgstr "{month} {year} göre yazılar" +msgid "Posts for {month} {day}, {year}" +msgstr "{month} {day}, {year} 'den beri olan yazılar" + msgid "Nothing found." msgstr "Hiçbir şey bulunamadı." @@ -107,7 +113,22 @@ msgid "RSS feed" msgstr "RSS kaynağı" msgid "%d min remaining to read" -msgstr "" +msgstr "%d dakikalık okuma" msgid "Skip to main content" +msgstr "Ana içeriğe geç" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/uk.po b/translations/nikola.messages/uk.po new file mode 100644 index 0000000..f2b8f6c --- /dev/null +++ b/translations/nikola.messages/uk.po @@ -0,0 +1,132 @@ +# Messages in Nikola +# Copyright (C) 2012-2013 +# This file is distributed under the same license as the Nikola package. +# +# Translators: +# Translators: +# Translators: +# Translators: +# Translators: +# Alex Fedorov <frodo@my.ua>, 2015 +msgid "" +msgstr "" +"Project-Id-Version: Nikola\n" +"Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" +"POT-Creation-Date: 2013-03-15 12:24-0300\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" +"Language-Team: Ukrainian (http://www.transifex.com/projects/p/nikola/language/uk/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: uk\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "More posts about %s" +msgstr "Більше статей про %s" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "LANGUAGE" +msgstr "Українська" + +msgid "Tags" +msgstr "Теги" + +msgid "Categories" +msgstr "Категорії" + +msgid "Tags and Categories" +msgstr "Теги і категорії" + +msgid "Comments" +msgstr "Коментарі" + +msgid "Read more" +msgstr "Читати далі" + +msgid "Posts about %s" +msgstr "Статті про %s" + +msgid "Next post" +msgstr "Наступна стаття" + +msgid "old posts, page %d" +msgstr "старі статті, сторінка %d" + +msgid "page %d" +msgstr "сторінка %d" + +msgid "Source" +msgstr "Джерело" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "Read in English" +msgstr "Читати українською" + +msgid "Posts for year %s" +msgstr "Статті за %s рік" + +msgid "Newer posts" +msgstr "Нові статті" + +msgid "Previous post" +msgstr "Попередня стаття" + +msgid "Also available in:" +msgstr "Іншою мовою:" + +msgid "Languages:" +msgstr "Мови:" + +msgid "Original site" +msgstr "Оригінал сайту" + +msgid "Older posts" +msgstr "Більш старі статті" + +msgid "Archive" +msgstr "Архів" + +msgid "Publication date" +msgstr "Дата публікації" + +msgid "Posted:" +msgstr "Опублікована:" + +msgid "Posts for {month} {year}" +msgstr "Статті за {month} {year}" + +msgid "Posts for {month} {day}, {year}" +msgstr "Статті за {month} {day}, {year}" + +msgid "Nothing found." +msgstr "Нічого не знайдено" + +msgid "No posts found." +msgstr "Не знайдено жодної статті" + +msgid "RSS feed" +msgstr "RSS-стрічка" + +msgid "%d min remaining to read" +msgstr "Залишилось читати %d хвилин" + +msgid "Skip to main content" +msgstr "Перейти до основного матеріалу" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/ur.po b/translations/nikola.messages/ur.po index 3d626ab..3add26e 100644 --- a/translations/nikola.messages/ur.po +++ b/translations/nikola.messages/ur.po @@ -6,16 +6,18 @@ # Translators: # Translators: # Translators: +# Translators: # seanpue <a@seanpue.com>, 2014 # saadat, 2013 -# Saadat M. <nastaliq@gmail.com>, 2013-2014 -# Saadat M. <nastaliq@gmail.com>, 2013 +# Saadat M. <saadat@saadatmand.pk>, 2013-2014 +# Saadat M. <saadat@saadatmand.pk>, 2015 +# Saadat M. <saadat@saadatmand.pk>, 2013 msgid "" msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Urdu (http://www.transifex.com/projects/p/nikola/language/ur/)\n" "MIME-Version: 1.0\n" @@ -27,6 +29,8 @@ msgstr "" msgid "More posts about %s" msgstr "%s کے بارے میں مزید تحاریر" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "اردو" @@ -43,7 +47,7 @@ msgid "Comments" msgstr "تبصرے" msgid "Read more" -msgstr "مزید پڑھیے" +msgstr "مزید پڑھیں" msgid "Posts about %s" msgstr "%s کے بارے میں تحاریر" @@ -60,10 +64,10 @@ msgstr "صفحہ %d" msgid "Source" msgstr "سورس" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" -msgstr "اردو میں پڑھیے" +msgstr "اردو میں پڑھیں" msgid "Posts for year %s" msgstr "سال %s کی تحاریر" @@ -98,6 +102,9 @@ msgstr "اشاعت:" msgid "Posts for {month} {year}" msgstr "{month} {year} کی تحاریر" +msgid "Posts for {month} {day}, {year}" +msgstr "{day} {month}، {year} کی تحاریر" + msgid "Nothing found." msgstr "کچھ نہیں مل سکا۔" @@ -111,4 +118,19 @@ msgid "%d min remaining to read" msgstr "%d منٹ کا مطالعہ باقی" msgid "Skip to main content" +msgstr "مرکزی متن پر جائیں" + +msgid "Subcategories:" +msgstr "ذیلی زمرے" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." msgstr "" diff --git a/translations/nikola.messages/zh_CN.po b/translations/nikola.messages/zh_CN.po index b0abbe2..8368ff8 100644 --- a/translations/nikola.messages/zh_CN.po +++ b/translations/nikola.messages/zh_CN.po @@ -6,6 +6,7 @@ # Translators: # Translators: # Translators: +# Translators: # Christopher Meng <cickumqt@gmail.com>, 2013 # Kade For <kadefor@gmail.com>, 2013 # Kade For <kadefor@gmail.com>, 2013 @@ -16,7 +17,7 @@ msgstr "" "Project-Id-Version: Nikola\n" "Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" "POT-Creation-Date: 2013-03-15 12:24-0300\n" -"PO-Revision-Date: 2014-07-31 12:30+0000\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" "Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" "Language-Team: Chinese (China) (http://www.transifex.com/projects/p/nikola/language/zh_CN/)\n" "MIME-Version: 1.0\n" @@ -28,6 +29,8 @@ msgstr "" msgid "More posts about %s" msgstr "更多相关文章: %s" +#. Here your translation should NOT say English but the name of your language +#. instead msgid "LANGUAGE" msgstr "简体中文" @@ -61,7 +64,7 @@ msgstr "" msgid "Source" msgstr "源代码" -#. Here your translation should not say English but the name of your language +#. Here your translation should NOT say English but the name of your language #. instead msgid "Read in English" msgstr "中文版" @@ -99,6 +102,9 @@ msgstr "发表于:" msgid "Posts for {month} {year}" msgstr "{year}年{month}月文章" +msgid "Posts for {month} {day}, {year}" +msgstr "" + msgid "Nothing found." msgstr "" @@ -113,3 +119,18 @@ msgstr "" msgid "Skip to main content" msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" diff --git a/translations/nikola.messages/zh_TW.po b/translations/nikola.messages/zh_TW.po new file mode 100644 index 0000000..9d9b055 --- /dev/null +++ b/translations/nikola.messages/zh_TW.po @@ -0,0 +1,131 @@ +# Messages in Nikola +# Copyright (C) 2012-2013 +# This file is distributed under the same license as the Nikola package. +# +# Translators: +# Translators: +# Translators: +# Translators: +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: Nikola\n" +"Report-Msgid-Bugs-To: ralsina@netmanagers.com.ar\n" +"POT-Creation-Date: 2013-03-15 12:24-0300\n" +"PO-Revision-Date: 2015-06-24 12:06+0000\n" +"Last-Translator: Chris Warrick <kwpolska@gmail.com>\n" +"Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/nikola/language/zh_TW/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: zh_TW\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "More posts about %s" +msgstr "" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "LANGUAGE" +msgstr "" + +msgid "Tags" +msgstr "" + +msgid "Categories" +msgstr "" + +msgid "Tags and Categories" +msgstr "" + +msgid "Comments" +msgstr "" + +msgid "Read more" +msgstr "" + +msgid "Posts about %s" +msgstr "" + +msgid "Next post" +msgstr "" + +msgid "old posts, page %d" +msgstr "" + +msgid "page %d" +msgstr "" + +msgid "Source" +msgstr "" + +#. Here your translation should NOT say English but the name of your language +#. instead +msgid "Read in English" +msgstr "" + +msgid "Posts for year %s" +msgstr "" + +msgid "Newer posts" +msgstr "" + +msgid "Previous post" +msgstr "" + +msgid "Also available in:" +msgstr "" + +msgid "Languages:" +msgstr "" + +msgid "Original site" +msgstr "" + +msgid "Older posts" +msgstr "" + +msgid "Archive" +msgstr "" + +msgid "Publication date" +msgstr "" + +msgid "Posted:" +msgstr "" + +msgid "Posts for {month} {year}" +msgstr "" + +msgid "Posts for {month} {day}, {year}" +msgstr "" + +msgid "Nothing found." +msgstr "" + +msgid "No posts found." +msgstr "" + +msgid "RSS feed" +msgstr "" + +msgid "%d min remaining to read" +msgstr "" + +msgid "Skip to main content" +msgstr "" + +msgid "Subcategories:" +msgstr "" + +#. Used for active navigation links, for screen readers only +msgid "(active)" +msgstr "" + +#. Default content for a new post +msgid "Write your post here." +msgstr "" + +#. Default content for a new page +msgid "Write your page here." +msgstr "" |
