Changeset - 7037365a7bc3
dev_requirements.txt
Show inline comments
 
pytest >= 4.6.6, < 5.5
 
pytest >= 4.6.6, < 6.3
 
pytest-sugar >= 0.9.2, < 0.10
 
pytest-benchmark >= 3.2.2, < 3.3
 
pytest-localserver >= 0.5.0, < 0.6
 
mock >= 3.0.0, < 4.1
 
Sphinx >= 1.8.0, < 3.1
 
Sphinx >= 1.8.0, < 5.2
 
WebTest >= 2.0.6, < 2.1
 
isort == 5.1.2
 
pyflakes == 2.2.0
docs/conf.py
Show inline comments
 
@@ -38,25 +38,25 @@ templates_path = ['_templates']
 

	
 
# The suffix of source filenames.
 
source_suffix = '.rst'
 

	
 
# The encoding of source files.
 
#source_encoding = 'utf-8-sig'
 

	
 
# The master toctree document.
 
master_doc = 'index'
 

	
 
# General information about the project.
 
project = 'Kallithea'
 
copyright = '2010-2021 by various authors, licensed as GPLv3.'
 
copyright = '2010-2022 by various authors, licensed as GPLv3.'
 

	
 
# The version info for the project you're documenting, acts as replacement for
 
# |version| and |release|, also used in various other places throughout the
 
# built documents.
 
#
 
# The short X.Y version.
 
root = os.path.dirname(os.path.dirname(__file__))
 
sys.path.append(root)
 
version = kallithea.__version__
 
# The full version, including alpha/beta/rc tags.
 
release = kallithea.__version__
 

	
kallithea/config/application.py
Show inline comments
 
@@ -26,25 +26,25 @@ __all__ = ['make_app']
 

	
 

	
 
def wrap_app(app):
 
    """Wrap the TG WSGI application in Kallithea middleware"""
 
    config = app.config
 

	
 
    # we want our low level middleware to get to the request ASAP. We don't
 
    # need any stack middleware in them - especially no StatusCodeRedirect buffering
 
    app = SimpleHg(app, config)
 
    app = SimpleGit(app, config)
 

	
 
    # Enable https redirects based on HTTP_X_URL_SCHEME set by proxy
 
    if any(asbool(config.get(x)) for x in ['url_scheme_variable', 'force_https', 'use_htsts']):
 
    if config.get('url_scheme_variable') or asbool(config.get('force_https')) or asbool(config.get('use_htsts')):
 
        app = HttpsFixup(app, config)
 

	
 
    app = PermanentRepoUrl(app, config)
 

	
 
    # Optional and undocumented wrapper - gives more verbose request/response logging, but has a slight overhead
 
    if asbool(config.get('use_wsgi_wrapper')):
 
        app = RequestWrapper(app, config)
 

	
 
    return app
 

	
 

	
 
def make_app(global_conf, **app_conf):
kallithea/config/middleware/https_fixup.py
Show inline comments
 
@@ -17,25 +17,24 @@ kallithea.config.middleware.https_fixup
 

	
 
middleware to handle https correctly
 

	
 
This file was forked by the Kallithea project in July 2014.
 
Original author and date, and relevant copyright and licensing information is below:
 
:created_on: May 23, 2010
 
:author: marcink
 
:copyright: (c) 2013 RhodeCode GmbH, and others.
 
:license: GPLv3, see LICENSE.md for more details.
 
"""
 

	
 

	
 
import kallithea
 
from kallithea.lib.utils2 import asbool
 

	
 

	
 
class HttpsFixup(object):
 

	
 
    def __init__(self, app, config):
 
        self.application = app
 
        self.config = config
 

	
 
    def __call__(self, environ, start_response):
 
        self.__fixup(environ)
 
        debug = asbool(self.config.get('debug'))
 
@@ -53,19 +52,19 @@ class HttpsFixup(object):
 
        """
 
        Function to fixup the environ as needed. In order to use this
 
        middleware you should set this header inside your
 
        proxy ie. nginx, apache etc.
 
        """
 
        proto = None
 

	
 
        # if we have force, just override
 
        if asbool(self.config.get('force_https')):
 
            proto = 'https'
 
        else:
 
            # get protocol from configured WSGI environment variable
 
            url_scheme_variable = kallithea.CONFIG.get('url_scheme_variable')
 
            url_scheme_variable = self.config.get('url_scheme_variable')
 
            if url_scheme_variable:
 
                proto = environ.get(url_scheme_variable)
 

	
 
        if proto:
 
            environ['wsgi._org_proto'] = environ.get('wsgi.url_scheme')
 
            environ['wsgi.url_scheme'] = proto
kallithea/controllers/admin/repo_groups.py
Show inline comments
 
@@ -236,49 +236,50 @@ class RepoGroupsController(base.BaseCont
 
                encoding="UTF-8",
 
                force_defaults=False)
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            webutils.flash(_('Error occurred during update of repository group %s')
 
                    % request.POST.get('group_name'), category='error')
 

	
 
        raise HTTPFound(location=url('edit_repo_group', group_name=group_name))
 

	
 
    @HasRepoGroupPermissionLevelDecorator('admin')
 
    def delete(self, group_name):
 
        gr = c.repo_group = db.RepoGroup.guess_instance(group_name)
 
        parent_group = gr.parent_group
 
        repos = gr.repositories.all()
 
        if repos:
 
            webutils.flash(_('This group contains %s repositories and cannot be '
 
                      'deleted') % len(repos), category='warning')
 
            raise HTTPFound(location=url('repos_groups'))
 

	
 
        children = gr.children.all()
 
        if children:
 
            webutils.flash(_('This group contains %s subgroups and cannot be deleted'
 
                      % (len(children))), category='warning')
 
            raise HTTPFound(location=url('repos_groups'))
 

	
 
        try:
 
            RepoGroupModel().delete(group_name)
 
            meta.Session().commit()
 
            webutils.flash(_('Removed repository group %s') % group_name,
 
                    category='success')
 
            # TODO: in future action_logger(, '', '', '')
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            webutils.flash(_('Error occurred during deletion of repository group %s')
 
                    % group_name, category='error')
 

	
 
        if gr.parent_group:
 
            raise HTTPFound(location=url('repos_group_home', group_name=gr.parent_group.group_name))
 
        if parent_group:
 
            raise HTTPFound(location=url('repos_group_home', group_name=parent_group.group_name))
 
        raise HTTPFound(location=url('repos_groups'))
 

	
 
    def show_by_name(self, group_name):
 
        """
 
        This is a proxy that does a lookup group_name -> id, and shows
 
        the group by id view instead
 
        """
 
        group_name = group_name.rstrip('/')
 
        id_ = db.RepoGroup.get_by_group_name(group_name)
 
        if id_:
 
            return self.show(group_name)
 
        raise HTTPNotFound
kallithea/controllers/changelog.py
Show inline comments
 
@@ -105,25 +105,25 @@ class ChangelogController(base.BaseRepoC
 
                tip_cs = c.db_repo_scm_instance.get_changeset()
 
                try:
 
                    collection = tip_cs.get_file_history(f_path)
 
                except (NodeDoesNotExistError, ChangesetError):
 
                    # this node is not present at tip !
 
                    try:
 
                        cs = self.__get_cs(revision, repo_name)
 
                        collection = cs.get_file_history(f_path)
 
                    except RepositoryError as e:
 
                        webutils.flash(e, category='warning')
 
                        raise HTTPFound(location=webutils.url('changelog_home', repo_name=repo_name))
 
            else:
 
                collection = c.db_repo_scm_instance.get_changesets(start=0, end=revision,
 
                collection = c.db_repo_scm_instance.get_changesets(end=revision,
 
                                                        branch_name=branch_name, reverse=True)
 
            c.total_cs = len(collection)
 

	
 
            c.cs_pagination = Page(collection, page=p, item_count=c.total_cs, items_per_page=c.size,
 
                                   branch=branch_name)
 

	
 
            page_revisions = [x.raw_id for x in c.cs_pagination]
 
            c.cs_comments = c.db_repo.get_comments(page_revisions)
 
            c.cs_statuses = c.db_repo.statuses(page_revisions)
 
        except EmptyRepositoryError as e:
 
            webutils.flash(e, category='warning')
 
            raise HTTPFound(location=url('summary_home', repo_name=c.repo_name))
kallithea/controllers/files.py
Show inline comments
 
@@ -35,25 +35,25 @@ from collections import OrderedDict
 

	
 
from tg import request, response
 
from tg import tmpl_context as c
 
from tg.i18n import ugettext as _
 
from webob.exc import HTTPFound, HTTPNotFound
 

	
 
import kallithea
 
import kallithea.lib.helpers as h
 
from kallithea.controllers import base
 
from kallithea.lib import diffs, webutils
 
from kallithea.lib.auth import HasRepoPermissionLevelDecorator, LoginRequired
 
from kallithea.lib.exceptions import NonRelativePathError
 
from kallithea.lib.utils2 import asbool, convert_line_endings, detect_mode, safe_str
 
from kallithea.lib.utils2 import asbool, convert_line_endings, detect_mode, safe_bytes, safe_str
 
from kallithea.lib.vcs.backends.base import EmptyChangeset
 
from kallithea.lib.vcs.conf import settings
 
from kallithea.lib.vcs.exceptions import (ChangesetDoesNotExistError, ChangesetError, EmptyRepositoryError, ImproperArchiveTypeError, NodeAlreadyExistsError,
 
                                          NodeDoesNotExistError, NodeError, RepositoryError, VCSError)
 
from kallithea.lib.vcs.nodes import FileNode
 
from kallithea.lib.vcs.utils import author_email
 
from kallithea.lib.webutils import url
 
from kallithea.model import userlog
 
from kallithea.model.repo import RepoModel
 
from kallithea.model.scm import ScmModel
 

	
 

	
 
@@ -224,25 +224,25 @@ class FilesController(base.BaseRepoContr
 
            c.authors = []
 
            for a in set([x.author for x in _hist]):
 
                c.authors.append((author_email(a), h.person(a)))
 
            return base.render('files/files_history_box.html')
 

	
 
    @LoginRequired(allow_default_user=True)
 
    @HasRepoPermissionLevelDecorator('read')
 
    def rawfile(self, repo_name, revision, f_path):
 
        cs = self.__get_cs(revision)
 
        file_node = self.__get_filenode(cs, f_path)
 

	
 
        response.content_disposition = \
 
            'attachment; filename=%s' % f_path.split(kallithea.URL_SEP)[-1]
 
            'attachment; filename=%s' % safe_bytes(f_path.split(kallithea.URL_SEP)[-1]).decode('latin1')
 

	
 
        response.content_type = file_node.mimetype
 
        return file_node.content
 

	
 
    @LoginRequired(allow_default_user=True)
 
    @HasRepoPermissionLevelDecorator('read')
 
    def raw(self, repo_name, revision, f_path):
 
        cs = self.__get_cs(revision)
 
        file_node = self.__get_filenode(cs, f_path)
 

	
 
        raw_mimetype_mapping = {
 
            # map original mimetype to a mimetype used for "show as raw"
kallithea/front-end/package-lock.json
Show inline comments
 
{
 
  "name": "kallithea",
 
  "lockfileVersion": 2,
 
  "requires": true,
 
  "lockfileVersion": 1,
 
  "packages": {
 
    "": {
 
      "name": "kallithea",
 
      "dependencies": {
 
        "at.js": "1.5.4",
 
        "bootstrap": "3.3.7",
 
        "codemirror": "5.49.0",
 
        "datatables.net": "1.10.20",
 
        "datatables.net-bs": "1.10.20",
 
        "jquery": "3.4.1",
 
        "jquery.caret": "0.3.1",
 
        "jquery.flot": "0.8.3",
 
        "select2": "3.5.1",
 
        "select2-bootstrap-css": "1.4.6"
 
      },
 
      "devDependencies": {
 
        "eslint": "6.8.0",
 
        "eslint-plugin-html": "6.0.0",
 
        "less": "3.10.3",
 
        "less-plugin-clean-css": "1.5.1",
 
        "license-checker": "25.0.1"
 
      }
 
    },
 
    "node_modules/@babel/code-frame": {
 
      "version": "7.8.3",
 
      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
 
      "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
 
      "dev": true,
 
      "dependencies": {
 
        "@babel/highlight": "^7.8.3"
 
      }
 
    },
 
    "node_modules/@babel/highlight": {
 
      "version": "7.8.3",
 
      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
 
      "integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
 
      "dev": true,
 
      "dependencies": {
 
        "chalk": "^2.0.0",
 
        "esutils": "^2.0.2",
 
        "js-tokens": "^4.0.0"
 
      }
 
    },
 
    "node_modules/abbrev": {
 
      "version": "1.1.1",
 
      "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
 
      "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
 
      "dev": true
 
    },
 
    "node_modules/acorn": {
 
      "version": "7.1.0",
 
      "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
 
      "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==",
 
      "dev": true,
 
      "bin": {
 
        "acorn": "bin/acorn"
 
      },
 
      "engines": {
 
        "node": ">=0.4.0"
 
      }
 
    },
 
    "node_modules/acorn-jsx": {
 
      "version": "5.1.0",
 
      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz",
 
      "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==",
 
      "dev": true,
 
      "peerDependencies": {
 
        "acorn": "^6.0.0 || ^7.0.0"
 
      }
 
    },
 
    "node_modules/ajv": {
 
      "version": "6.10.2",
 
      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
 
      "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
 
      "dev": true,
 
      "dependencies": {
 
        "fast-deep-equal": "^2.0.1",
 
        "fast-json-stable-stringify": "^2.0.0",
 
        "json-schema-traverse": "^0.4.1",
 
        "uri-js": "^4.2.2"
 
      }
 
    },
 
    "node_modules/amdefine": {
 
      "version": "1.0.1",
 
      "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
 
      "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.4.2"
 
      }
 
    },
 
    "node_modules/ansi-escapes": {
 
      "version": "4.3.0",
 
      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.0.tgz",
 
      "integrity": "sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg==",
 
      "dev": true,
 
      "dependencies": {
 
        "type-fest": "^0.8.1"
 
      },
 
      "engines": {
 
        "node": ">=8"
 
      }
 
    },
 
    "node_modules/ansi-regex": {
 
      "version": "5.0.0",
 
      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
 
      "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=8"
 
      }
 
    },
 
    "node_modules/ansi-styles": {
 
      "version": "3.2.1",
 
      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
 
      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
 
      "dev": true,
 
      "dependencies": {
 
        "color-convert": "^1.9.0"
 
      },
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/argparse": {
 
      "version": "1.0.10",
 
      "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
 
      "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
 
      "dev": true,
 
      "dependencies": {
 
        "sprintf-js": "~1.0.2"
 
      }
 
    },
 
    "node_modules/array-find-index": {
 
      "version": "1.0.2",
 
      "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
 
      "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/asap": {
 
      "version": "2.0.6",
 
      "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
 
      "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=",
 
      "dev": true
 
    },
 
    "node_modules/asn1": {
 
      "version": "0.2.4",
 
      "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
 
      "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "safer-buffer": "~2.1.0"
 
      }
 
    },
 
    "node_modules/assert-plus": {
 
      "version": "1.0.0",
 
      "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
 
      "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=",
 
      "dev": true,
 
      "optional": true,
 
      "engines": {
 
        "node": ">=0.8"
 
      }
 
    },
 
    "node_modules/astral-regex": {
 
      "version": "1.0.0",
 
      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
 
      "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/asynckit": {
 
      "version": "0.4.0",
 
      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
 
      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/at.js": {
 
      "version": "1.5.4",
 
      "resolved": "https://registry.npmjs.org/at.js/-/at.js-1.5.4.tgz",
 
      "integrity": "sha512-G8mgUb/PqShPoH8AyjuxsTGvIr1o716BtQUKDM44C8qN2W615y7KGJ68MlTGamd0J0D/m28emUkzagaHTdrGZw==",
 
      "engines": {
 
        "node": ">= 0.6.0"
 
      },
 
      "peerDependencies": {
 
        "jquery": ">=1.7.0 <4.0.0"
 
      }
 
    },
 
    "node_modules/aws-sign2": {
 
      "version": "0.7.0",
 
      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
 
      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
 
      "dev": true,
 
      "optional": true,
 
      "engines": {
 
        "node": "*"
 
      }
 
    },
 
    "node_modules/aws4": {
 
      "version": "1.8.0",
 
      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
 
      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/balanced-match": {
 
      "version": "1.0.0",
 
      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
 
      "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
 
      "dev": true
 
    },
 
    "node_modules/bcrypt-pbkdf": {
 
      "version": "1.0.2",
 
      "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
 
      "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "tweetnacl": "^0.14.3"
 
      }
 
    },
 
    "node_modules/bootstrap": {
 
      "version": "3.3.7",
 
      "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-3.3.7.tgz",
 
      "integrity": "sha1-WjiTlFSfIzMIdaOxUGVldPip63E=",
 
      "engines": {
 
        "node": ">=0.10.1"
 
      }
 
    },
 
    "node_modules/brace-expansion": {
 
      "version": "1.1.11",
 
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
 
      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
 
      "dev": true,
 
      "dependencies": {
 
        "balanced-match": "^1.0.0",
 
        "concat-map": "0.0.1"
 
      }
 
    },
 
    "node_modules/callsites": {
 
      "version": "3.1.0",
 
      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
 
      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=6"
 
      }
 
    },
 
    "node_modules/caseless": {
 
      "version": "0.12.0",
 
      "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
 
      "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/chalk": {
 
      "version": "2.4.2",
 
      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
 
      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
 
      "dev": true,
 
      "dependencies": {
 
        "ansi-styles": "^3.2.1",
 
        "escape-string-regexp": "^1.0.5",
 
        "supports-color": "^5.3.0"
 
      },
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/chardet": {
 
      "version": "0.7.0",
 
      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
 
      "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
 
      "dev": true
 
    },
 
    "node_modules/clean-css": {
 
      "version": "3.4.28",
 
      "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz",
 
      "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=",
 
      "dev": true,
 
      "dependencies": {
 
        "commander": "2.8.x",
 
        "source-map": "0.4.x"
 
      },
 
      "bin": {
 
        "cleancss": "bin/cleancss"
 
      },
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/clean-css/node_modules/source-map": {
 
      "version": "0.4.4",
 
      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
 
      "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
 
      "dev": true,
 
      "dependencies": {
 
        "amdefine": ">=0.0.4"
 
      },
 
      "engines": {
 
        "node": ">=0.8.0"
 
      }
 
    },
 
    "node_modules/cli-cursor": {
 
      "version": "3.1.0",
 
      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
 
      "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
 
      "dev": true,
 
      "dependencies": {
 
        "restore-cursor": "^3.1.0"
 
      },
 
      "engines": {
 
        "node": ">=8"
 
      }
 
    },
 
    "node_modules/cli-width": {
 
      "version": "2.2.0",
 
      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz",
 
      "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=",
 
      "dev": true
 
    },
 
    "node_modules/clone": {
 
      "version": "2.1.2",
 
      "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
 
      "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.8"
 
      }
 
    },
 
    "node_modules/codemirror": {
 
      "version": "5.49.0",
 
      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.49.0.tgz",
 
      "integrity": "sha512-Hyzr0HToBdZpLBN9dYFO/KlJAsKH37/cXVHPAqa+imml0R92tb9AkmsvjnXL+SluEvjjdfkDgRjc65NG5jnMYA=="
 
    },
 
    "node_modules/color-convert": {
 
      "version": "1.9.3",
 
      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
 
      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
 
      "dev": true,
 
      "dependencies": {
 
        "color-name": "1.1.3"
 
      }
 
    },
 
    "node_modules/color-name": {
 
      "version": "1.1.3",
 
      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
 
      "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
 
      "dev": true
 
    },
 
    "node_modules/combined-stream": {
 
      "version": "1.0.8",
 
      "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
 
      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "delayed-stream": "~1.0.0"
 
      },
 
      "engines": {
 
        "node": ">= 0.8"
 
      }
 
    },
 
    "node_modules/commander": {
 
      "version": "2.8.1",
 
      "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz",
 
      "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=",
 
      "dev": true,
 
      "dependencies": {
 
        "graceful-readlink": ">= 1.0.0"
 
      },
 
      "engines": {
 
        "node": ">= 0.6.x"
 
      }
 
    },
 
    "node_modules/concat-map": {
 
      "version": "0.0.1",
 
      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
 
      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
 
      "dev": true
 
    },
 
    "node_modules/core-util-is": {
 
      "version": "1.0.2",
 
      "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
 
      "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/cross-spawn": {
 
      "version": "6.0.5",
 
      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
 
      "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
 
      "dev": true,
 
      "dependencies": {
 
        "nice-try": "^1.0.4",
 
        "path-key": "^2.0.1",
 
        "semver": "^5.5.0",
 
        "shebang-command": "^1.2.0",
 
        "which": "^1.2.9"
 
      },
 
      "engines": {
 
        "node": ">=4.8"
 
      }
 
    },
 
    "node_modules/dashdash": {
 
      "version": "1.14.1",
 
      "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
 
      "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "assert-plus": "^1.0.0"
 
      },
 
      "engines": {
 
        "node": ">=0.10"
 
      }
 
    },
 
    "node_modules/datatables.net": {
 
      "version": "1.10.20",
 
      "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-1.10.20.tgz",
 
      "integrity": "sha512-4E4S7tTU607N3h0fZPkGmAtr9mwy462u+VJ6gxYZ8MxcRIjZqHy3Dv1GNry7i3zQCktTdWbULVKBbkAJkuHEnQ==",
 
      "dependencies": {
 
        "jquery": ">=1.7"
 
      }
 
    },
 
    "node_modules/datatables.net-bs": {
 
      "version": "1.10.20",
 
      "resolved": "https://registry.npmjs.org/datatables.net-bs/-/datatables.net-bs-1.10.20.tgz",
 
      "integrity": "sha512-NsMoOOYZ6NlteOpzhltw21lXsNdhjIMbIOxnqmcrb62ntl8eL9pYzk2AeiDXBlIKY4e550ZrExCq3CYKQ9myEg==",
 
      "dependencies": {
 
        "datatables.net": "1.10.20",
 
        "jquery": ">=1.7"
 
      }
 
    },
 
    "node_modules/debug": {
 
      "version": "3.2.6",
 
      "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
 
      "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
 
      "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
 
      "dev": true,
 
      "dependencies": {
 
        "ms": "^2.1.1"
 
      }
 
    },
 
    "node_modules/debuglog": {
 
      "version": "1.0.1",
 
      "resolved": "https://registry.npmjs.org/debuglog/-/debuglog-1.0.1.tgz",
 
      "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=",
 
      "dev": true,
 
      "engines": {
 
        "node": "*"
 
      }
 
    },
 
    "node_modules/deep-is": {
 
      "version": "0.1.3",
 
      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz",
 
      "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
 
      "dev": true
 
    },
 
    "node_modules/delayed-stream": {
 
      "version": "1.0.0",
 
      "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
 
      "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
 
      "dev": true,
 
      "optional": true,
 
      "engines": {
 
        "node": ">=0.4.0"
 
      }
 
    },
 
    "node_modules/dezalgo": {
 
      "version": "1.0.3",
 
      "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.3.tgz",
 
      "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=",
 
      "dev": true,
 
      "dependencies": {
 
        "asap": "^2.0.0",
 
        "wrappy": "1"
 
      }
 
    },
 
    "node_modules/doctrine": {
 
      "version": "3.0.0",
 
      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
 
      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
 
      "dev": true,
 
      "dependencies": {
 
        "esutils": "^2.0.2"
 
      },
 
      "engines": {
 
        "node": ">=6.0.0"
 
      }
 
    },
 
    "node_modules/dom-serializer": {
 
      "version": "0.2.2",
 
      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
 
      "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
 
      "dev": true,
 
      "dependencies": {
 
        "domelementtype": "^2.0.1",
 
        "entities": "^2.0.0"
 
      }
 
    },
 
    "node_modules/dom-serializer/node_modules/domelementtype": {
 
      "version": "2.0.1",
 
      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
 
      "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==",
 
      "dev": true
 
    },
 
    "node_modules/dom-serializer/node_modules/entities": {
 
      "version": "2.0.0",
 
      "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
 
      "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==",
 
      "dev": true
 
    },
 
    "node_modules/domelementtype": {
 
      "version": "1.3.1",
 
      "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
 
      "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
 
      "dev": true
 
    },
 
    "node_modules/domhandler": {
 
      "version": "2.4.2",
 
      "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
 
      "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
 
      "dev": true,
 
      "dependencies": {
 
        "domelementtype": "1"
 
      }
 
    },
 
    "node_modules/domutils": {
 
      "version": "1.7.0",
 
      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
 
      "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
 
      "dev": true,
 
      "dependencies": {
 
        "dom-serializer": "0",
 
        "domelementtype": "1"
 
      }
 
    },
 
    "node_modules/ecc-jsbn": {
 
      "version": "0.1.2",
 
      "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
 
      "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "jsbn": "~0.1.0",
 
        "safer-buffer": "^2.1.0"
 
      }
 
    },
 
    "node_modules/emoji-regex": {
 
      "version": "8.0.0",
 
      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
 
      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
 
      "dev": true
 
    },
 
    "node_modules/entities": {
 
      "version": "1.1.2",
 
      "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
 
      "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
 
      "dev": true
 
    },
 
    "node_modules/errno": {
 
      "version": "0.1.7",
 
      "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
 
      "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "prr": "~1.0.1"
 
      },
 
      "bin": {
 
        "errno": "cli.js"
 
      }
 
    },
 
    "node_modules/escape-string-regexp": {
 
      "version": "1.0.5",
 
      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
 
      "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.8.0"
 
      }
 
    },
 
    "node_modules/eslint": {
 
      "version": "6.8.0",
 
      "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
 
      "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==",
 
      "dev": true,
 
      "dependencies": {
 
        "@babel/code-frame": "^7.0.0",
 
        "ajv": "^6.10.0",
 
        "chalk": "^2.1.0",
 
        "cross-spawn": "^6.0.5",
 
        "debug": "^4.0.1",
 
        "doctrine": "^3.0.0",
 
        "eslint-scope": "^5.0.0",
 
        "eslint-utils": "^1.4.3",
 
        "eslint-visitor-keys": "^1.1.0",
 
        "espree": "^6.1.2",
 
        "esquery": "^1.0.1",
 
        "esutils": "^2.0.2",
 
        "file-entry-cache": "^5.0.1",
 
        "functional-red-black-tree": "^1.0.1",
 
        "glob-parent": "^5.0.0",
 
        "globals": "^12.1.0",
 
        "ignore": "^4.0.6",
 
        "import-fresh": "^3.0.0",
 
        "imurmurhash": "^0.1.4",
 
        "inquirer": "^7.0.0",
 
        "is-glob": "^4.0.0",
 
        "js-yaml": "^3.13.1",
 
        "json-stable-stringify-without-jsonify": "^1.0.1",
 
        "levn": "^0.3.0",
 
        "lodash": "^4.17.14",
 
        "minimatch": "^3.0.4",
 
        "mkdirp": "^0.5.1",
 
        "natural-compare": "^1.4.0",
 
        "optionator": "^0.8.3",
 
        "progress": "^2.0.0",
 
        "regexpp": "^2.0.1",
 
        "semver": "^6.1.2",
 
        "strip-ansi": "^5.2.0",
 
        "strip-json-comments": "^3.0.1",
 
        "table": "^5.2.3",
 
        "text-table": "^0.2.0",
 
        "v8-compile-cache": "^2.0.3"
 
      },
 
      "bin": {
 
        "eslint": "bin/eslint.js"
 
      },
 
      "engines": {
 
        "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
 
      },
 
      "funding": {
 
        "url": "https://opencollective.com/eslint"
 
      }
 
    },
 
    "node_modules/eslint-plugin-html": {
 
      "version": "6.0.0",
 
      "resolved": "https://registry.npmjs.org/eslint-plugin-html/-/eslint-plugin-html-6.0.0.tgz",
 
      "integrity": "sha512-PQcGippOHS+HTbQCStmH5MY1BF2MaU8qW/+Mvo/8xTa/ioeMXdSP+IiaBw2+nh0KEMfYQKuTz1Zo+vHynjwhbg==",
 
      "dev": true,
 
      "dependencies": {
 
        "htmlparser2": "^3.10.1"
 
      }
 
    },
 
    "node_modules/eslint-scope": {
 
      "version": "5.0.0",
 
      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.0.0.tgz",
 
      "integrity": "sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw==",
 
      "dev": true,
 
      "dependencies": {
 
        "esrecurse": "^4.1.0",
 
        "estraverse": "^4.1.1"
 
      },
 
      "engines": {
 
        "node": ">=8.0.0"
 
      }
 
    },
 
    "node_modules/eslint-utils": {
 
      "version": "1.4.3",
 
      "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
 
      "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
 
      "dev": true,
 
      "dependencies": {
 
        "eslint-visitor-keys": "^1.1.0"
 
      },
 
      "engines": {
 
        "node": ">=6"
 
      }
 
    },
 
    "node_modules/eslint-visitor-keys": {
 
      "version": "1.1.0",
 
      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz",
 
      "integrity": "sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/eslint/node_modules/debug": {
 
      "version": "4.1.1",
 
      "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
 
      "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
 
      "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)",
 
      "dev": true,
 
      "dependencies": {
 
        "ms": "^2.1.1"
 
      }
 
    },
 
    "node_modules/eslint/node_modules/semver": {
 
      "version": "6.3.0",
 
      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
 
      "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
 
      "dev": true,
 
      "bin": {
 
        "semver": "bin/semver.js"
 
      }
 
    },
 
    "node_modules/espree": {
 
      "version": "6.1.2",
 
      "resolved": "https://registry.npmjs.org/espree/-/espree-6.1.2.tgz",
 
      "integrity": "sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA==",
 
      "dev": true,
 
      "dependencies": {
 
        "acorn": "^7.1.0",
 
        "acorn-jsx": "^5.1.0",
 
        "eslint-visitor-keys": "^1.1.0"
 
      },
 
      "engines": {
 
        "node": ">=6.0.0"
 
      }
 
    },
 
    "node_modules/esprima": {
 
      "version": "4.0.1",
 
      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
 
      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
 
      "dev": true,
 
      "bin": {
 
        "esparse": "bin/esparse.js",
 
        "esvalidate": "bin/esvalidate.js"
 
      },
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/esquery": {
 
      "version": "1.1.0",
 
      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.1.0.tgz",
 
      "integrity": "sha512-MxYW9xKmROWF672KqjO75sszsA8Mxhw06YFeS5VHlB98KDHbOSurm3ArsjO60Eaf3QmGMCP1yn+0JQkNLo/97Q==",
 
      "dev": true,
 
      "dependencies": {
 
        "estraverse": "^4.0.0"
 
      },
 
      "engines": {
 
        "node": ">=0.6"
 
      }
 
    },
 
    "node_modules/esrecurse": {
 
      "version": "4.2.1",
 
      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
 
      "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
 
      "dev": true,
 
      "dependencies": {
 
        "estraverse": "^4.1.0"
 
      },
 
      "engines": {
 
        "node": ">=4.0"
 
      }
 
    },
 
    "node_modules/estraverse": {
 
      "version": "4.3.0",
 
      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
 
      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=4.0"
 
      }
 
    },
 
    "node_modules/esutils": {
 
      "version": "2.0.3",
 
      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
 
      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/extend": {
 
      "version": "3.0.2",
 
      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
 
      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/external-editor": {
 
      "version": "3.1.0",
 
      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
 
      "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
 
      "dev": true,
 
      "dependencies": {
 
        "chardet": "^0.7.0",
 
        "iconv-lite": "^0.4.24",
 
        "tmp": "^0.0.33"
 
      },
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/extsprintf": {
 
      "version": "1.3.0",
 
      "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
 
      "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=",
 
      "dev": true,
 
      "engines": [
 
        "node >=0.6.0"
 
      ],
 
      "optional": true
 
    },
 
    "node_modules/fast-deep-equal": {
 
      "version": "2.0.1",
 
      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
 
      "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=",
 
      "dev": true
 
    },
 
    "node_modules/fast-json-stable-stringify": {
 
      "version": "2.0.0",
 
      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
 
      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=",
 
      "dev": true
 
    },
 
    "node_modules/fast-levenshtein": {
 
      "version": "2.0.6",
 
      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
 
      "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=",
 
      "dev": true
 
    },
 
    "node_modules/figures": {
 
      "version": "3.2.0",
 
      "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
 
      "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
 
      "dev": true,
 
      "dependencies": {
 
        "escape-string-regexp": "^1.0.5"
 
      },
 
      "engines": {
 
        "node": ">=8"
 
      },
 
      "funding": {
 
        "url": "https://github.com/sponsors/sindresorhus"
 
      }
 
    },
 
    "node_modules/file-entry-cache": {
 
      "version": "5.0.1",
 
      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
 
      "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
 
      "dev": true,
 
      "dependencies": {
 
        "flat-cache": "^2.0.1"
 
      },
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/flat-cache": {
 
      "version": "2.0.1",
 
      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
 
      "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
 
      "dev": true,
 
      "dependencies": {
 
        "flatted": "^2.0.0",
 
        "rimraf": "2.6.3",
 
        "write": "1.0.3"
 
      },
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/flatted": {
 
      "version": "2.0.1",
 
      "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.1.tgz",
 
      "integrity": "sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg==",
 
      "dev": true
 
    },
 
    "node_modules/forever-agent": {
 
      "version": "0.6.1",
 
      "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
 
      "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=",
 
      "dev": true,
 
      "optional": true,
 
      "engines": {
 
        "node": "*"
 
      }
 
    },
 
    "node_modules/form-data": {
 
      "version": "2.3.3",
 
      "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
 
      "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "asynckit": "^0.4.0",
 
        "combined-stream": "^1.0.6",
 
        "mime-types": "^2.1.12"
 
      },
 
      "engines": {
 
        "node": ">= 0.12"
 
      }
 
    },
 
    "node_modules/fs.realpath": {
 
      "version": "1.0.0",
 
      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
 
      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
 
      "dev": true
 
    },
 
    "node_modules/functional-red-black-tree": {
 
      "version": "1.0.1",
 
      "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
 
      "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
 
      "dev": true
 
    },
 
    "node_modules/getpass": {
 
      "version": "0.1.7",
 
      "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
 
      "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "assert-plus": "^1.0.0"
 
      }
 
    },
 
    "node_modules/glob": {
 
      "version": "7.1.6",
 
      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
 
      "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
 
      "dev": true,
 
      "dependencies": {
 
        "fs.realpath": "^1.0.0",
 
        "inflight": "^1.0.4",
 
        "inherits": "2",
 
        "minimatch": "^3.0.4",
 
        "once": "^1.3.0",
 
        "path-is-absolute": "^1.0.0"
 
      },
 
      "engines": {
 
        "node": "*"
 
      },
 
      "funding": {
 
        "url": "https://github.com/sponsors/isaacs"
 
      }
 
    },
 
    "node_modules/glob-parent": {
 
      "version": "5.1.0",
 
      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.0.tgz",
 
      "integrity": "sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw==",
 
      "dev": true,
 
      "dependencies": {
 
        "is-glob": "^4.0.1"
 
      },
 
      "engines": {
 
        "node": ">= 6"
 
      }
 
    },
 
    "node_modules/globals": {
 
      "version": "12.3.0",
 
      "resolved": "https://registry.npmjs.org/globals/-/globals-12.3.0.tgz",
 
      "integrity": "sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw==",
 
      "dev": true,
 
      "dependencies": {
 
        "type-fest": "^0.8.1"
 
      },
 
      "engines": {
 
        "node": ">=8"
 
      }
 
    },
 
    "node_modules/graceful-fs": {
 
      "version": "4.2.3",
 
      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz",
 
      "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==",
 
      "dev": true
 
    },
 
    "node_modules/graceful-readlink": {
 
      "version": "1.0.1",
 
      "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz",
 
      "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=",
 
      "dev": true
 
    },
 
    "node_modules/har-schema": {
 
      "version": "2.0.0",
 
      "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
 
      "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=",
 
      "dev": true,
 
      "optional": true,
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/har-validator": {
 
      "version": "5.1.3",
 
      "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
 
      "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
 
      "deprecated": "this library is no longer supported",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "ajv": "^6.5.5",
 
        "har-schema": "^2.0.0"
 
      },
 
      "engines": {
 
        "node": ">=6"
 
      }
 
    },
 
    "node_modules/has-flag": {
 
      "version": "3.0.0",
 
      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
 
      "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/hosted-git-info": {
 
      "version": "2.8.5",
 
      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.5.tgz",
 
      "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==",
 
      "dev": true
 
    },
 
    "node_modules/htmlparser2": {
 
      "version": "3.10.1",
 
      "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
 
      "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
 
      "dev": true,
 
      "dependencies": {
 
        "domelementtype": "^1.3.1",
 
        "domhandler": "^2.3.0",
 
        "domutils": "^1.5.1",
 
        "entities": "^1.1.1",
 
        "inherits": "^2.0.1",
 
        "readable-stream": "^3.1.1"
 
      }
 
    },
 
    "node_modules/http-signature": {
 
      "version": "1.2.0",
 
      "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
 
      "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "assert-plus": "^1.0.0",
 
        "jsprim": "^1.2.2",
 
        "sshpk": "^1.7.0"
 
      },
 
      "engines": {
 
        "node": ">=0.8",
 
        "npm": ">=1.3.7"
 
      }
 
    },
 
    "node_modules/iconv-lite": {
 
      "version": "0.4.24",
 
      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
 
      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
 
      "dev": true,
 
      "dependencies": {
 
        "safer-buffer": ">= 2.1.2 < 3"
 
      },
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/ignore": {
 
      "version": "4.0.6",
 
      "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
 
      "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">= 4"
 
      }
 
    },
 
    "node_modules/image-size": {
 
      "version": "0.5.5",
 
      "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz",
 
      "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=",
 
      "dev": true,
 
      "optional": true,
 
      "bin": {
 
        "image-size": "bin/image-size.js"
 
      },
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/import-fresh": {
 
      "version": "3.2.1",
 
      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz",
 
      "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==",
 
      "dev": true,
 
      "dependencies": {
 
        "parent-module": "^1.0.0",
 
        "resolve-from": "^4.0.0"
 
      },
 
      "engines": {
 
        "node": ">=6"
 
      }
 
    },
 
    "node_modules/imurmurhash": {
 
      "version": "0.1.4",
 
      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
 
      "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.8.19"
 
      }
 
    },
 
    "node_modules/inflight": {
 
      "version": "1.0.6",
 
      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
 
      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
 
      "dev": true,
 
      "dependencies": {
 
        "once": "^1.3.0",
 
        "wrappy": "1"
 
      }
 
    },
 
    "node_modules/inherits": {
 
      "version": "2.0.4",
 
      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
 
      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
 
      "dev": true
 
    },
 
    "node_modules/inquirer": {
 
      "version": "7.0.4",
 
      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.0.4.tgz",
 
      "integrity": "sha512-Bu5Td5+j11sCkqfqmUTiwv+tWisMtP0L7Q8WrqA2C/BbBhy1YTdFrvjjlrKq8oagA/tLQBski2Gcx/Sqyi2qSQ==",
 
      "dev": true,
 
      "dependencies": {
 
        "ansi-escapes": "^4.2.1",
 
        "chalk": "^2.4.2",
 
        "cli-cursor": "^3.1.0",
 
        "cli-width": "^2.0.0",
 
        "external-editor": "^3.0.3",
 
        "figures": "^3.0.0",
 
        "lodash": "^4.17.15",
 
        "mute-stream": "0.0.8",
 
        "run-async": "^2.2.0",
 
        "rxjs": "^6.5.3",
 
        "string-width": "^4.1.0",
 
        "strip-ansi": "^5.1.0",
 
        "through": "^2.3.6"
 
      },
 
      "engines": {
 
        "node": ">=6.0.0"
 
      }
 
    },
 
    "node_modules/is-extglob": {
 
      "version": "2.1.1",
 
      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
 
      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/is-fullwidth-code-point": {
 
      "version": "3.0.0",
 
      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
 
      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=8"
 
      }
 
    },
 
    "node_modules/is-glob": {
 
      "version": "4.0.1",
 
      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
 
      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
 
      "dev": true,
 
      "dependencies": {
 
        "is-extglob": "^2.1.1"
 
      },
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/is-promise": {
 
      "version": "2.1.0",
 
      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
 
      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
 
      "dev": true
 
    },
 
    "node_modules/is-typedarray": {
 
      "version": "1.0.0",
 
      "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
 
      "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/isexe": {
 
      "version": "2.0.0",
 
      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
 
      "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
 
      "dev": true
 
    },
 
    "node_modules/isstream": {
 
      "version": "0.1.2",
 
      "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
 
      "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/jquery": {
 
      "version": "3.4.1",
 
      "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.4.1.tgz",
 
      "integrity": "sha512-36+AdBzCL+y6qjw5Tx7HgzeGCzC81MDDgaUP8ld2zhx58HdqXGoBd+tHdrBMiyjGQs0Hxs/MLZTu/eHNJJuWPw=="
 
    },
 
    "node_modules/jquery.caret": {
 
      "version": "0.3.1",
 
      "resolved": "https://registry.npmjs.org/jquery.caret/-/jquery.caret-0.3.1.tgz",
 
      "integrity": "sha1-nAkzGPrzJ+/zIugmyp8yQTaLx7g="
 
    },
 
    "node_modules/jquery.flot": {
 
      "version": "0.8.3",
 
      "resolved": "https://registry.npmjs.org/jquery.flot/-/jquery.flot-0.8.3.tgz",
 
      "integrity": "sha512-/tEE8J5NjwvStHDaCHkvTJpD7wDS4hE1OEL8xEmhgQfUe0gLUem923PIceNez1mz4yBNx6Hjv7pJcowLNd+nbg=="
 
    },
 
    "node_modules/js-tokens": {
 
      "version": "4.0.0",
 
      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
 
      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
 
      "dev": true
 
    },
 
    "node_modules/js-yaml": {
 
      "version": "3.13.1",
 
      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
 
      "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
 
      "dev": true,
 
      "dependencies": {
 
        "argparse": "^1.0.7",
 
        "esprima": "^4.0.0"
 
      },
 
      "bin": {
 
        "js-yaml": "bin/js-yaml.js"
 
      }
 
    },
 
    "node_modules/jsbn": {
 
      "version": "0.1.1",
 
      "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
 
      "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/json-parse-better-errors": {
 
      "version": "1.0.2",
 
      "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
 
      "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
 
      "dev": true
 
    },
 
    "node_modules/json-schema": {
 
      "version": "0.2.3",
 
      "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
 
      "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/json-schema-traverse": {
 
      "version": "0.4.1",
 
      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
 
      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
 
      "dev": true
 
    },
 
    "node_modules/json-stable-stringify-without-jsonify": {
 
      "version": "1.0.1",
 
      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
 
      "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=",
 
      "dev": true
 
    },
 
    "node_modules/json-stringify-safe": {
 
      "version": "5.0.1",
 
      "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
 
      "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/jsprim": {
 
      "version": "1.4.1",
 
      "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
 
      "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
 
      "dev": true,
 
      "engines": [
 
        "node >=0.6.0"
 
      ],
 
      "optional": true,
 
      "dependencies": {
 
        "assert-plus": "1.0.0",
 
        "extsprintf": "1.3.0",
 
        "json-schema": "0.2.3",
 
        "verror": "1.10.0"
 
      }
 
    },
 
    "node_modules/less": {
 
      "version": "3.10.3",
 
      "resolved": "https://registry.npmjs.org/less/-/less-3.10.3.tgz",
 
      "integrity": "sha512-vz32vqfgmoxF1h3K4J+yKCtajH0PWmjkIFgbs5d78E/c/e+UQTnI+lWK+1eQRE95PXM2mC3rJlLSSP9VQHnaow==",
 
      "dev": true,
 
      "dependencies": {
 
        "clone": "^2.1.2"
 
      },
 
      "bin": {
 
        "lessc": "bin/lessc"
 
      },
 
      "engines": {
 
        "node": ">=6"
 
      },
 
      "optionalDependencies": {
 
        "errno": "^0.1.1",
 
        "graceful-fs": "^4.1.2",
 
        "image-size": "~0.5.0",
 
        "mime": "^1.4.1",
 
        "mkdirp": "^0.5.0",
 
        "promise": "^7.1.1",
 
        "request": "^2.83.0",
 
        "source-map": "~0.6.0"
 
      }
 
    },
 
    "node_modules/less-plugin-clean-css": {
 
      "version": "1.5.1",
 
      "resolved": "https://registry.npmjs.org/less-plugin-clean-css/-/less-plugin-clean-css-1.5.1.tgz",
 
      "integrity": "sha1-zFeveqM5iVflbezr5jy2DCNClwM=",
 
      "dev": true,
 
      "dependencies": {
 
        "clean-css": "^3.0.1"
 
      },
 
      "engines": {
 
        "node": ">=0.4.2"
 
      }
 
    },
 
    "node_modules/levn": {
 
      "version": "0.3.0",
 
      "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
 
      "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=",
 
      "dev": true,
 
      "dependencies": {
 
        "prelude-ls": "~1.1.2",
 
        "type-check": "~0.3.2"
 
      },
 
      "engines": {
 
        "node": ">= 0.8.0"
 
      }
 
    },
 
    "node_modules/license-checker": {
 
      "version": "25.0.1",
 
      "resolved": "https://registry.npmjs.org/license-checker/-/license-checker-25.0.1.tgz",
 
      "integrity": "sha512-mET5AIwl7MR2IAKYYoVBBpV0OnkKQ1xGj2IMMeEFIs42QAkEVjRtFZGWmQ28WeU7MP779iAgOaOy93Mn44mn6g==",
 
      "dev": true,
 
      "dependencies": {
 
        "chalk": "^2.4.1",
 
        "debug": "^3.1.0",
 
        "mkdirp": "^0.5.1",
 
        "nopt": "^4.0.1",
 
        "read-installed": "~4.0.3",
 
        "semver": "^5.5.0",
 
        "spdx-correct": "^3.0.0",
 
        "spdx-expression-parse": "^3.0.0",
 
        "spdx-satisfies": "^4.0.0",
 
        "treeify": "^1.1.0"
 
      },
 
      "bin": {
 
        "license-checker": "bin/license-checker"
 
      }
 
    },
 
    "node_modules/lodash": {
 
      "version": "4.17.15",
 
      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
 
      "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
 
      "dev": true
 
    },
 
    "node_modules/mime": {
 
      "version": "1.6.0",
 
      "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
 
      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
 
      "dev": true,
 
      "optional": true,
 
      "bin": {
 
        "mime": "cli.js"
 
      },
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/mime-db": {
 
      "version": "1.40.0",
 
      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
 
      "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==",
 
      "dev": true,
 
      "optional": true,
 
      "engines": {
 
        "node": ">= 0.6"
 
      }
 
    },
 
    "node_modules/mime-types": {
 
      "version": "2.1.24",
 
      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
 
      "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "mime-db": "1.40.0"
 
      },
 
      "engines": {
 
        "node": ">= 0.6"
 
      }
 
    },
 
    "node_modules/mimic-fn": {
 
      "version": "2.1.0",
 
      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
 
      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=6"
 
      }
 
    },
 
    "node_modules/minimatch": {
 
      "version": "3.0.4",
 
      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
 
      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
 
      "dev": true,
 
      "dependencies": {
 
        "brace-expansion": "^1.1.7"
 
      },
 
      "engines": {
 
        "node": "*"
 
      }
 
    },
 
    "node_modules/minimist": {
 
      "version": "0.0.8",
 
      "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
 
      "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
 
      "dev": true
 
    },
 
    "node_modules/mkdirp": {
 
      "version": "0.5.1",
 
      "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
 
      "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
 
      "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)",
 
      "dev": true,
 
      "dependencies": {
 
        "minimist": "0.0.8"
 
      },
 
      "bin": {
 
        "mkdirp": "bin/cmd.js"
 
      }
 
    },
 
    "node_modules/ms": {
 
      "version": "2.1.2",
 
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
 
      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
 
      "dev": true
 
    },
 
    "node_modules/mute-stream": {
 
      "version": "0.0.8",
 
      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
 
      "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
 
      "dev": true
 
    },
 
    "node_modules/natural-compare": {
 
      "version": "1.4.0",
 
      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
 
      "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
 
      "dev": true
 
    },
 
    "node_modules/nice-try": {
 
      "version": "1.0.5",
 
      "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
 
      "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
 
      "dev": true
 
    },
 
    "node_modules/nopt": {
 
      "version": "4.0.1",
 
      "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz",
 
      "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=",
 
      "dev": true,
 
      "dependencies": {
 
        "abbrev": "1",
 
        "osenv": "^0.1.4"
 
      },
 
      "bin": {
 
        "nopt": "bin/nopt.js"
 
      }
 
    },
 
    "node_modules/normalize-package-data": {
 
      "version": "2.5.0",
 
      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
 
      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
 
      "dev": true,
 
      "dependencies": {
 
        "hosted-git-info": "^2.1.4",
 
        "resolve": "^1.10.0",
 
        "semver": "2 || 3 || 4 || 5",
 
        "validate-npm-package-license": "^3.0.1"
 
      }
 
    },
 
    "node_modules/oauth-sign": {
 
      "version": "0.9.0",
 
      "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
 
      "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
 
      "dev": true,
 
      "optional": true,
 
      "engines": {
 
        "node": "*"
 
      }
 
    },
 
    "node_modules/once": {
 
      "version": "1.4.0",
 
      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
 
      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
 
      "dev": true,
 
      "dependencies": {
 
        "wrappy": "1"
 
      }
 
    },
 
    "node_modules/onetime": {
 
      "version": "5.1.0",
 
      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz",
 
      "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==",
 
      "dev": true,
 
      "dependencies": {
 
        "mimic-fn": "^2.1.0"
 
      },
 
      "engines": {
 
        "node": ">=6"
 
      }
 
    },
 
    "node_modules/optionator": {
 
      "version": "0.8.3",
 
      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
 
      "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
 
      "dev": true,
 
      "dependencies": {
 
        "deep-is": "~0.1.3",
 
        "fast-levenshtein": "~2.0.6",
 
        "levn": "~0.3.0",
 
        "prelude-ls": "~1.1.2",
 
        "type-check": "~0.3.2",
 
        "word-wrap": "~1.2.3"
 
      },
 
      "engines": {
 
        "node": ">= 0.8.0"
 
      }
 
    },
 
    "node_modules/os-homedir": {
 
      "version": "1.0.2",
 
      "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz",
 
      "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/os-tmpdir": {
 
      "version": "1.0.2",
 
      "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
 
      "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/osenv": {
 
      "version": "0.1.5",
 
      "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
 
      "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
 
      "dev": true,
 
      "dependencies": {
 
        "os-homedir": "^1.0.0",
 
        "os-tmpdir": "^1.0.0"
 
      }
 
    },
 
    "node_modules/parent-module": {
 
      "version": "1.0.1",
 
      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
 
      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
 
      "dev": true,
 
      "dependencies": {
 
        "callsites": "^3.0.0"
 
      },
 
      "engines": {
 
        "node": ">=6"
 
      }
 
    },
 
    "node_modules/path-is-absolute": {
 
      "version": "1.0.1",
 
      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
 
      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/path-key": {
 
      "version": "2.0.1",
 
      "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
 
      "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/path-parse": {
 
      "version": "1.0.6",
 
      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
 
      "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
 
      "dev": true
 
    },
 
    "node_modules/performance-now": {
 
      "version": "2.1.0",
 
      "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
 
      "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/prelude-ls": {
 
      "version": "1.1.2",
 
      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
 
      "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">= 0.8.0"
 
      }
 
    },
 
    "node_modules/progress": {
 
      "version": "2.0.3",
 
      "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
 
      "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.4.0"
 
      }
 
    },
 
    "node_modules/promise": {
 
      "version": "7.3.1",
 
      "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
 
      "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "asap": "~2.0.3"
 
      }
 
    },
 
    "node_modules/prr": {
 
      "version": "1.0.1",
 
      "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
 
      "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/psl": {
 
      "version": "1.4.0",
 
      "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz",
 
      "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/punycode": {
 
      "version": "2.1.1",
 
      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
 
      "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=6"
 
      }
 
    },
 
    "node_modules/qs": {
 
      "version": "6.5.2",
 
      "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
 
      "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
 
      "dev": true,
 
      "optional": true,
 
      "engines": {
 
        "node": ">=0.6"
 
      }
 
    },
 
    "node_modules/read-installed": {
 
      "version": "4.0.3",
 
      "resolved": "https://registry.npmjs.org/read-installed/-/read-installed-4.0.3.tgz",
 
      "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=",
 
      "dev": true,
 
      "dependencies": {
 
        "debuglog": "^1.0.1",
 
        "read-package-json": "^2.0.0",
 
        "readdir-scoped-modules": "^1.0.0",
 
        "semver": "2 || 3 || 4 || 5",
 
        "slide": "~1.1.3",
 
        "util-extend": "^1.0.1"
 
      },
 
      "optionalDependencies": {
 
        "graceful-fs": "^4.1.2"
 
      }
 
    },
 
    "node_modules/read-package-json": {
 
      "version": "2.1.0",
 
      "resolved": "https://registry.npmjs.org/read-package-json/-/read-package-json-2.1.0.tgz",
 
      "integrity": "sha512-KLhu8M1ZZNkMcrq1+0UJbR8Dii8KZUqB0Sha4mOx/bknfKI/fyrQVrG/YIt2UOtG667sD8+ee4EXMM91W9dC+A==",
 
      "dev": true,
 
      "dependencies": {
 
        "glob": "^7.1.1",
 
        "json-parse-better-errors": "^1.0.1",
 
        "normalize-package-data": "^2.0.0",
 
        "slash": "^1.0.0"
 
      },
 
      "optionalDependencies": {
 
        "graceful-fs": "^4.1.2"
 
      }
 
    },
 
    "node_modules/readable-stream": {
 
      "version": "3.6.0",
 
      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
 
      "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
 
      "dev": true,
 
      "dependencies": {
 
        "inherits": "^2.0.3",
 
        "string_decoder": "^1.1.1",
 
        "util-deprecate": "^1.0.1"
 
      },
 
      "engines": {
 
        "node": ">= 6"
 
      }
 
    },
 
    "node_modules/readdir-scoped-modules": {
 
      "version": "1.1.0",
 
      "resolved": "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz",
 
      "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==",
 
      "dev": true,
 
      "dependencies": {
 
        "debuglog": "^1.0.1",
 
        "dezalgo": "^1.0.0",
 
        "graceful-fs": "^4.1.2",
 
        "once": "^1.3.0"
 
      }
 
    },
 
    "node_modules/regexpp": {
 
      "version": "2.0.1",
 
      "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
 
      "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=6.5.0"
 
      }
 
    },
 
    "node_modules/request": {
 
      "version": "2.88.0",
 
      "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
 
      "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
 
      "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "aws-sign2": "~0.7.0",
 
        "aws4": "^1.8.0",
 
        "caseless": "~0.12.0",
 
        "combined-stream": "~1.0.6",
 
        "extend": "~3.0.2",
 
        "forever-agent": "~0.6.1",
 
        "form-data": "~2.3.2",
 
        "har-validator": "~5.1.0",
 
        "http-signature": "~1.2.0",
 
        "is-typedarray": "~1.0.0",
 
        "isstream": "~0.1.2",
 
        "json-stringify-safe": "~5.0.1",
 
        "mime-types": "~2.1.19",
 
        "oauth-sign": "~0.9.0",
 
        "performance-now": "^2.1.0",
 
        "qs": "~6.5.2",
 
        "safe-buffer": "^5.1.2",
 
        "tough-cookie": "~2.4.3",
 
        "tunnel-agent": "^0.6.0",
 
        "uuid": "^3.3.2"
 
      },
 
      "engines": {
 
        "node": ">= 4"
 
      }
 
    },
 
    "node_modules/resolve": {
 
      "version": "1.12.0",
 
      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz",
 
      "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==",
 
      "dev": true,
 
      "dependencies": {
 
        "path-parse": "^1.0.6"
 
      }
 
    },
 
    "node_modules/resolve-from": {
 
      "version": "4.0.0",
 
      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
 
      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/restore-cursor": {
 
      "version": "3.1.0",
 
      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
 
      "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
 
      "dev": true,
 
      "dependencies": {
 
        "onetime": "^5.1.0",
 
        "signal-exit": "^3.0.2"
 
      },
 
      "engines": {
 
        "node": ">=8"
 
      }
 
    },
 
    "node_modules/rimraf": {
 
      "version": "2.6.3",
 
      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
 
      "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
 
      "dev": true,
 
      "dependencies": {
 
        "glob": "^7.1.3"
 
      },
 
      "bin": {
 
        "rimraf": "bin.js"
 
      }
 
    },
 
    "node_modules/run-async": {
 
      "version": "2.3.0",
 
      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz",
 
      "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=",
 
      "dev": true,
 
      "dependencies": {
 
        "is-promise": "^2.1.0"
 
      },
 
      "engines": {
 
        "node": ">=0.12.0"
 
      }
 
    },
 
    "node_modules/rxjs": {
 
      "version": "6.5.4",
 
      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.4.tgz",
 
      "integrity": "sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q==",
 
      "dev": true,
 
      "dependencies": {
 
        "tslib": "^1.9.0"
 
      },
 
      "engines": {
 
        "npm": ">=2.0.0"
 
      }
 
    },
 
    "node_modules/safe-buffer": {
 
      "version": "5.2.0",
 
      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
 
      "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==",
 
      "dev": true
 
    },
 
    "node_modules/safer-buffer": {
 
      "version": "2.1.2",
 
      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
 
      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
 
      "dev": true
 
    },
 
    "node_modules/select2": {
 
      "version": "3.5.1",
 
      "resolved": "https://registry.npmjs.org/select2/-/select2-3.5.1.tgz",
 
      "integrity": "sha1-8oGUibvGX9bTKL5yu+K5XdfofP4="
 
    },
 
    "node_modules/select2-bootstrap-css": {
 
      "version": "1.4.6",
 
      "resolved": "https://registry.npmjs.org/select2-bootstrap-css/-/select2-bootstrap-css-1.4.6.tgz",
 
      "integrity": "sha1-XPtoJG9SmcoYWOAe/XiIBMc0mX4="
 
    },
 
    "node_modules/semver": {
 
      "version": "5.7.1",
 
      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
 
      "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
 
      "dev": true,
 
      "bin": {
 
        "semver": "bin/semver"
 
      }
 
    },
 
    "node_modules/shebang-command": {
 
      "version": "1.2.0",
 
      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
 
      "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
 
      "dev": true,
 
      "dependencies": {
 
        "shebang-regex": "^1.0.0"
 
      },
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/shebang-regex": {
 
      "version": "1.0.0",
 
      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
 
      "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/signal-exit": {
 
      "version": "3.0.2",
 
      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
 
      "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=",
 
      "dev": true
 
    },
 
    "node_modules/slash": {
 
      "version": "1.0.0",
 
      "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
 
      "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/slice-ansi": {
 
      "version": "2.1.0",
 
      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
 
      "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
 
      "dev": true,
 
      "dependencies": {
 
        "ansi-styles": "^3.2.0",
 
        "astral-regex": "^1.0.0",
 
        "is-fullwidth-code-point": "^2.0.0"
 
      },
 
      "engines": {
 
        "node": ">=6"
 
      }
 
    },
 
    "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
 
      "version": "2.0.0",
 
      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
 
      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/slide": {
 
      "version": "1.1.6",
 
      "resolved": "https://registry.npmjs.org/slide/-/slide-1.1.6.tgz",
 
      "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=",
 
      "dev": true,
 
      "engines": {
 
        "node": "*"
 
      }
 
    },
 
    "node_modules/source-map": {
 
      "version": "0.6.1",
 
      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
 
      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
 
      "dev": true,
 
      "optional": true,
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/spdx-compare": {
 
      "version": "1.0.0",
 
      "resolved": "https://registry.npmjs.org/spdx-compare/-/spdx-compare-1.0.0.tgz",
 
      "integrity": "sha512-C1mDZOX0hnu0ep9dfmuoi03+eOdDoz2yvK79RxbcrVEG1NO1Ph35yW102DHWKN4pk80nwCgeMmSY5L25VE4D9A==",
 
      "dev": true,
 
      "dependencies": {
 
        "array-find-index": "^1.0.2",
 
        "spdx-expression-parse": "^3.0.0",
 
        "spdx-ranges": "^2.0.0"
 
      }
 
    },
 
    "node_modules/spdx-correct": {
 
      "version": "3.1.0",
 
      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz",
 
      "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==",
 
      "dev": true,
 
      "dependencies": {
 
        "spdx-expression-parse": "^3.0.0",
 
        "spdx-license-ids": "^3.0.0"
 
      }
 
    },
 
    "node_modules/spdx-exceptions": {
 
      "version": "2.2.0",
 
      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz",
 
      "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==",
 
      "dev": true
 
    },
 
    "node_modules/spdx-expression-parse": {
 
      "version": "3.0.0",
 
      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz",
 
      "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==",
 
      "dev": true,
 
      "dependencies": {
 
        "spdx-exceptions": "^2.1.0",
 
        "spdx-license-ids": "^3.0.0"
 
      }
 
    },
 
    "node_modules/spdx-license-ids": {
 
      "version": "3.0.5",
 
      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz",
 
      "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==",
 
      "dev": true
 
    },
 
    "node_modules/spdx-ranges": {
 
      "version": "2.1.1",
 
      "resolved": "https://registry.npmjs.org/spdx-ranges/-/spdx-ranges-2.1.1.tgz",
 
      "integrity": "sha512-mcdpQFV7UDAgLpXEE/jOMqvK4LBoO0uTQg0uvXUewmEFhpiZx5yJSZITHB8w1ZahKdhfZqP5GPEOKLyEq5p8XA==",
 
      "dev": true
 
    },
 
    "node_modules/spdx-satisfies": {
 
      "version": "4.0.1",
 
      "resolved": "https://registry.npmjs.org/spdx-satisfies/-/spdx-satisfies-4.0.1.tgz",
 
      "integrity": "sha512-WVzZ/cXAzoNmjCWiEluEA3BjHp5tiUmmhn9MK+X0tBbR9sOqtC6UQwmgCNrAIZvNlMuBUYAaHYfb2oqlF9SwKA==",
 
      "dev": true,
 
      "dependencies": {
 
        "spdx-compare": "^1.0.0",
 
        "spdx-expression-parse": "^3.0.0",
 
        "spdx-ranges": "^2.0.0"
 
      }
 
    },
 
    "node_modules/sprintf-js": {
 
      "version": "1.0.3",
 
      "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
 
      "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
 
      "dev": true
 
    },
 
    "node_modules/sshpk": {
 
      "version": "1.16.1",
 
      "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
 
      "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "asn1": "~0.2.3",
 
        "assert-plus": "^1.0.0",
 
        "bcrypt-pbkdf": "^1.0.0",
 
        "dashdash": "^1.12.0",
 
        "ecc-jsbn": "~0.1.1",
 
        "getpass": "^0.1.1",
 
        "jsbn": "~0.1.0",
 
        "safer-buffer": "^2.0.2",
 
        "tweetnacl": "~0.14.0"
 
      },
 
      "bin": {
 
        "sshpk-conv": "bin/sshpk-conv",
 
        "sshpk-sign": "bin/sshpk-sign",
 
        "sshpk-verify": "bin/sshpk-verify"
 
      },
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/string_decoder": {
 
      "version": "1.3.0",
 
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
 
      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
 
      "dev": true,
 
      "dependencies": {
 
        "safe-buffer": "~5.2.0"
 
      }
 
    },
 
    "node_modules/string-width": {
 
      "version": "4.2.0",
 
      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
 
      "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
 
      "dev": true,
 
      "dependencies": {
 
        "emoji-regex": "^8.0.0",
 
        "is-fullwidth-code-point": "^3.0.0",
 
        "strip-ansi": "^6.0.0"
 
      },
 
      "engines": {
 
        "node": ">=8"
 
      }
 
    },
 
    "node_modules/string-width/node_modules/strip-ansi": {
 
      "version": "6.0.0",
 
      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
 
      "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
 
      "dev": true,
 
      "dependencies": {
 
        "ansi-regex": "^5.0.0"
 
      },
 
      "engines": {
 
        "node": ">=8"
 
      }
 
    },
 
    "node_modules/strip-ansi": {
 
      "version": "5.2.0",
 
      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
 
      "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
 
      "dev": true,
 
      "dependencies": {
 
        "ansi-regex": "^4.1.0"
 
      },
 
      "engines": {
 
        "node": ">=6"
 
      }
 
    },
 
    "node_modules/strip-ansi/node_modules/ansi-regex": {
 
      "version": "4.1.0",
 
      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
 
      "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=6"
 
      }
 
    },
 
    "node_modules/strip-json-comments": {
 
      "version": "3.0.1",
 
      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz",
 
      "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=8"
 
      }
 
    },
 
    "node_modules/supports-color": {
 
      "version": "5.5.0",
 
      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
 
      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
 
      "dev": true,
 
      "dependencies": {
 
        "has-flag": "^3.0.0"
 
      },
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/table": {
 
      "version": "5.4.6",
 
      "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
 
      "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
 
      "dev": true,
 
      "dependencies": {
 
        "ajv": "^6.10.2",
 
        "lodash": "^4.17.14",
 
        "slice-ansi": "^2.1.0",
 
        "string-width": "^3.0.0"
 
      },
 
      "engines": {
 
        "node": ">=6.0.0"
 
      }
 
    },
 
    "node_modules/table/node_modules/emoji-regex": {
 
      "version": "7.0.3",
 
      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
 
      "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
 
      "dev": true
 
    },
 
    "node_modules/table/node_modules/is-fullwidth-code-point": {
 
      "version": "2.0.0",
 
      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
 
      "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    },
 
    "node_modules/table/node_modules/string-width": {
 
      "version": "3.1.0",
 
      "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
 
      "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
 
      "dev": true,
 
      "dependencies": {
 
        "emoji-regex": "^7.0.1",
 
        "is-fullwidth-code-point": "^2.0.0",
 
        "strip-ansi": "^5.1.0"
 
      },
 
      "engines": {
 
        "node": ">=6"
 
      }
 
    },
 
    "node_modules/text-table": {
 
      "version": "0.2.0",
 
      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
 
      "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=",
 
      "dev": true
 
    },
 
    "node_modules/through": {
 
      "version": "2.3.8",
 
      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
 
      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
 
      "dev": true
 
    },
 
    "node_modules/tmp": {
 
      "version": "0.0.33",
 
      "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
 
      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
 
      "dev": true,
 
      "dependencies": {
 
        "os-tmpdir": "~1.0.2"
 
      },
 
      "engines": {
 
        "node": ">=0.6.0"
 
      }
 
    },
 
    "node_modules/tough-cookie": {
 
      "version": "2.4.3",
 
      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
 
      "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "psl": "^1.1.24",
 
        "punycode": "^1.4.1"
 
      },
 
      "engines": {
 
        "node": ">=0.8"
 
      }
 
    },
 
    "node_modules/tough-cookie/node_modules/punycode": {
 
      "version": "1.4.1",
 
      "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
 
      "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/treeify": {
 
      "version": "1.1.0",
 
      "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz",
 
      "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.6"
 
      }
 
    },
 
    "node_modules/tslib": {
 
      "version": "1.11.0",
 
      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.0.tgz",
 
      "integrity": "sha512-BmndXUtiTn/VDDrJzQE7Mm22Ix3PxgLltW9bSNLoeCY31gnG2OPx0QqJnuc9oMIKioYrz487i6K9o4Pdn0j+Kg==",
 
      "dev": true
 
    },
 
    "node_modules/tunnel-agent": {
 
      "version": "0.6.0",
 
      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
 
      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
 
      "dev": true,
 
      "optional": true,
 
      "dependencies": {
 
        "safe-buffer": "^5.0.1"
 
      },
 
      "engines": {
 
        "node": "*"
 
      }
 
    },
 
    "node_modules/tweetnacl": {
 
      "version": "0.14.5",
 
      "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
 
      "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "node_modules/type-check": {
 
      "version": "0.3.2",
 
      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
 
      "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=",
 
      "dev": true,
 
      "dependencies": {
 
        "prelude-ls": "~1.1.2"
 
      },
 
      "engines": {
 
        "node": ">= 0.8.0"
 
      }
 
    },
 
    "node_modules/type-fest": {
 
      "version": "0.8.1",
 
      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
 
      "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=8"
 
      }
 
    },
 
    "node_modules/uri-js": {
 
      "version": "4.2.2",
 
      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
 
      "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
 
      "dev": true,
 
      "dependencies": {
 
        "punycode": "^2.1.0"
 
      }
 
    },
 
    "node_modules/util-deprecate": {
 
      "version": "1.0.2",
 
      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
 
      "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
 
      "dev": true
 
    },
 
    "node_modules/util-extend": {
 
      "version": "1.0.3",
 
      "resolved": "https://registry.npmjs.org/util-extend/-/util-extend-1.0.3.tgz",
 
      "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=",
 
      "dev": true
 
    },
 
    "node_modules/uuid": {
 
      "version": "3.3.3",
 
      "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
 
      "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==",
 
      "deprecated": "Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.",
 
      "dev": true,
 
      "optional": true,
 
      "bin": {
 
        "uuid": "bin/uuid"
 
      }
 
    },
 
    "node_modules/v8-compile-cache": {
 
      "version": "2.1.0",
 
      "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz",
 
      "integrity": "sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g==",
 
      "dev": true
 
    },
 
    "node_modules/validate-npm-package-license": {
 
      "version": "3.0.4",
 
      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
 
      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
 
      "dev": true,
 
      "dependencies": {
 
        "spdx-correct": "^3.0.0",
 
        "spdx-expression-parse": "^3.0.0"
 
      }
 
    },
 
    "node_modules/verror": {
 
      "version": "1.10.0",
 
      "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
 
      "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
 
      "dev": true,
 
      "engines": [
 
        "node >=0.6.0"
 
      ],
 
      "optional": true,
 
      "dependencies": {
 
        "assert-plus": "^1.0.0",
 
        "core-util-is": "1.0.2",
 
        "extsprintf": "^1.2.0"
 
      }
 
    },
 
    "node_modules/which": {
 
      "version": "1.3.1",
 
      "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
 
      "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
 
      "dev": true,
 
      "dependencies": {
 
        "isexe": "^2.0.0"
 
      },
 
      "bin": {
 
        "which": "bin/which"
 
      }
 
    },
 
    "node_modules/word-wrap": {
 
      "version": "1.2.3",
 
      "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
 
      "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
 
      "dev": true,
 
      "engines": {
 
        "node": ">=0.10.0"
 
      }
 
    },
 
    "node_modules/wrappy": {
 
      "version": "1.0.2",
 
      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
 
      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
 
      "dev": true
 
    },
 
    "node_modules/write": {
 
      "version": "1.0.3",
 
      "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
 
      "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
 
      "dev": true,
 
      "dependencies": {
 
        "mkdirp": "^0.5.1"
 
      },
 
      "engines": {
 
        "node": ">=4"
 
      }
 
    }
 
  },
 
  "dependencies": {
 
    "@babel/code-frame": {
 
      "version": "7.8.3",
 
      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
 
      "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
 
      "dev": true,
 
      "requires": {
 
        "@babel/highlight": "^7.8.3"
 
      }
 
    },
 
    "@babel/highlight": {
 
      "version": "7.8.3",
 
@@ -30,25 +2390,26 @@
 
      "dev": true
 
    },
 
    "acorn": {
 
      "version": "7.1.0",
 
      "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz",
 
      "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==",
 
      "dev": true
 
    },
 
    "acorn-jsx": {
 
      "version": "5.1.0",
 
      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.1.0.tgz",
 
      "integrity": "sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw==",
 
      "dev": true
 
      "dev": true,
 
      "requires": {}
 
    },
 
    "ajv": {
 
      "version": "6.10.2",
 
      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
 
      "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
 
      "dev": true,
 
      "requires": {
 
        "fast-deep-equal": "^2.0.1",
 
        "fast-json-stable-stringify": "^2.0.0",
 
        "json-schema-traverse": "^0.4.1",
 
        "uri-js": "^4.2.2"
 
      }
 
@@ -128,25 +2489,26 @@
 
      "dev": true
 
    },
 
    "asynckit": {
 
      "version": "0.4.0",
 
      "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
 
      "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "at.js": {
 
      "version": "1.5.4",
 
      "resolved": "https://registry.npmjs.org/at.js/-/at.js-1.5.4.tgz",
 
      "integrity": "sha512-G8mgUb/PqShPoH8AyjuxsTGvIr1o716BtQUKDM44C8qN2W615y7KGJ68MlTGamd0J0D/m28emUkzagaHTdrGZw=="
 
      "integrity": "sha512-G8mgUb/PqShPoH8AyjuxsTGvIr1o716BtQUKDM44C8qN2W615y7KGJ68MlTGamd0J0D/m28emUkzagaHTdrGZw==",
 
      "requires": {}
 
    },
 
    "aws-sign2": {
 
      "version": "0.7.0",
 
      "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
 
      "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=",
 
      "dev": true,
 
      "optional": true
 
    },
 
    "aws4": {
 
      "version": "1.8.0",
 
      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
 
      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==",
 
@@ -1654,55 +4016,55 @@
 
      "requires": {
 
        "asn1": "~0.2.3",
 
        "assert-plus": "^1.0.0",
 
        "bcrypt-pbkdf": "^1.0.0",
 
        "dashdash": "^1.12.0",
 
        "ecc-jsbn": "~0.1.1",
 
        "getpass": "^0.1.1",
 
        "jsbn": "~0.1.0",
 
        "safer-buffer": "^2.0.2",
 
        "tweetnacl": "~0.14.0"
 
      }
 
    },
 
    "string_decoder": {
 
      "version": "1.3.0",
 
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
 
      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
 
      "dev": true,
 
      "requires": {
 
        "safe-buffer": "~5.2.0"
 
      }
 
    },
 
    "string-width": {
 
      "version": "4.2.0",
 
      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
 
      "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
 
      "dev": true,
 
      "requires": {
 
        "emoji-regex": "^8.0.0",
 
        "is-fullwidth-code-point": "^3.0.0",
 
        "strip-ansi": "^6.0.0"
 
      },
 
      "dependencies": {
 
        "strip-ansi": {
 
          "version": "6.0.0",
 
          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
 
          "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
 
          "dev": true,
 
          "requires": {
 
            "ansi-regex": "^5.0.0"
 
          }
 
        }
 
      }
 
    },
 
    "string_decoder": {
 
      "version": "1.3.0",
 
      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
 
      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
 
      "dev": true,
 
      "requires": {
 
        "safe-buffer": "~5.2.0"
 
      }
 
    },
 
    "strip-ansi": {
 
      "version": "5.2.0",
 
      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
 
      "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
 
      "dev": true,
 
      "requires": {
 
        "ansi-regex": "^4.1.0"
 
      },
 
      "dependencies": {
 
        "ansi-regex": {
 
          "version": "4.1.0",
 
          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
kallithea/lib/auth.py
Show inline comments
 
@@ -512,27 +512,27 @@ class LoginRequired(object):
 

	
 
    def __wrapper(self, func, *fargs, **fkwargs):
 
        controller = fargs[0]
 
        user = request.authuser
 
        loc = "%s:%s" % (controller.__class__.__name__, func.__name__)
 
        log.debug('Checking access for user %s @ %s', user, loc)
 

	
 
        # regular user authentication
 
        if user.is_default_user:
 
            if self.allow_default_user:
 
                log.info('default user @ %s', loc)
 
                return func(*fargs, **fkwargs)
 
            log.info('default user is not accepted here @ %s', loc)
 
            log.info('default user is redirected to login @ %s', loc)
 
        elif user.is_anonymous: # default user is disabled and no proper authentication
 
            log.warning('user is anonymous and NOT authenticated with regular auth @ %s', loc)
 
            log.info('anonymous user is redirected to login @ %s', loc)
 
        else: # regular authentication
 
            log.info('user %s authenticated with regular auth @ %s', user, loc)
 
            return func(*fargs, **fkwargs)
 
        raise _redirect_to_login()
 

	
 

	
 
# Use as decorator
 
class NotAnonymous(object):
 
    """Ensures that client is not logged in as the "default" user, and
 
    redirects to the login page otherwise. Must be used together with
 
    LoginRequired."""
 

	
kallithea/lib/markup_renderer.py
Show inline comments
 
@@ -108,25 +108,25 @@ class MarkupRenderer(object):
 
                      pre_insert_callback, text)
 

	
 
        return text
 

	
 
    @classmethod
 
    def render(cls, source, filename=None):
 
        """
 
        Renders a given filename using detected renderer
 
        it detects renderers based on file extension or mimetype.
 
        At last it will just do a simple html replacing new lines with <br/>
 

	
 
        >>> MarkupRenderer.render('''<img id="a" style="margin-top:-1000px;color:red" src="http://example.com/test.jpg">''', '.md')
 
        '<p><img id="a" src="http://example.com/test.jpg" style="color: red;"></p>'
 
        '<p><img id="a" src="http://example.com/test.jpg" style=""></p>'
 
        >>> MarkupRenderer.render('''<img class="c d" src="file://localhost/test.jpg">''', 'b.mkd')
 
        '<p><img class="c d"></p>'
 
        >>> MarkupRenderer.render('''<a href="foo">foo</a>''', 'c.mkdn')
 
        '<p><a href="foo">foo</a></p>'
 
        >>> MarkupRenderer.render('''<script>alert(1)</script>''', 'd.mdown')
 
        '&lt;script&gt;alert(1)&lt;/script&gt;'
 
        >>> MarkupRenderer.render('''<div onclick="alert(2)">yo</div>''', 'markdown')
 
        '<div>yo</div>'
 
        >>> MarkupRenderer.render('''<a href="javascript:alert(3)">yo</a>''', 'md')
 
        '<p><a>yo</a></p>'
 
        """
 

	
kallithea/lib/vcs/backends/base.py
Show inline comments
 
@@ -162,25 +162,25 @@ class BaseRepository(object):
 

	
 
    def get_changesets(self, start=None, end=None, start_date=None,
 
                       end_date=None, branch_name=None, reverse=False, max_revisions=None):
 
        """
 
        Returns iterator of ``BaseChangeset`` objects from start to end,
 
        both inclusive.
 

	
 
        :param start: None or str
 
        :param end: None or str
 
        :param start_date:
 
        :param end_date:
 
        :param branch_name:
 
        :param reversed:
 
        :param reverse:
 
        """
 
        raise NotImplementedError
 

	
 
    def get_diff_changesets(self, org_rev, other_repo, other_rev):
 
        """
 
        Returns lists of changesets that can be merged from this repo @org_rev
 
        to other_repo @other_rev
 
        ... and the other way
 
        ... and the ancestors that would be used for merge
 

	
 
        :param org_rev: the revision we want our compare to be made
 
        :param other_repo: repo object, most likely the fork of org_repo. It has
kallithea/lib/vcs/backends/git/repository.py
Show inline comments
 
@@ -10,25 +10,30 @@
 
"""
 

	
 
import errno
 
import logging
 
import os
 
import re
 
import time
 
import urllib.error
 
import urllib.parse
 
import urllib.request
 
from collections import OrderedDict
 

	
 
import mercurial.util  # import url as hg_url
 

	
 
try:
 
    from mercurial.utils.urlutil import url as hg_url
 
except ImportError:  # urlutil was introduced in Mercurial 5.8
 
    from mercurial.util import url as hg_url
 

	
 
from dulwich.client import SubprocessGitClient
 
from dulwich.config import ConfigFile
 
from dulwich.objects import Tag
 
from dulwich.repo import NotGitRepository, Repo
 
from dulwich.server import update_server_info
 

	
 
from kallithea.lib.vcs import subprocessio
 
from kallithea.lib.vcs.backends.base import BaseRepository, CollectionGenerator
 
from kallithea.lib.vcs.conf import settings
 
from kallithea.lib.vcs.exceptions import (BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, TagAlreadyExistError,
 
                                          TagDoesNotExistError)
 
from kallithea.lib.vcs.utils import ascii_bytes, ascii_str, date_fromtimestamp, makedate, safe_bytes, safe_str
 
@@ -217,25 +222,25 @@ class GitRepository(BaseRepository):
 
            # Don't trust urllib.parse.unquote but be prepared for more flexible implementations elsewhere.
 
            # Space is the only allowed whitespace character - directly or % encoded. No other % or \ is allowed.
 
            for c in parsed_url.path.replace('%20', ' '):
 
                if c in '%\\':
 
                    raise urllib.error.URLError("Invalid escape character in path: '%s'" % c)
 
                if c.isspace() and c != ' ':
 
                    raise urllib.error.URLError("Invalid whitespace character in path: %r" % c)
 
            return
 

	
 
        if parsed_url.scheme not in ['http', 'https']:
 
            raise urllib.error.URLError("Unsupported protocol in URL %r" % url)
 

	
 
        url_obj = mercurial.util.url(safe_bytes(url))
 
        url_obj = hg_url(safe_bytes(url))
 
        test_uri, handlers = get_urllib_request_handlers(url_obj)
 
        if not test_uri.endswith(b'info/refs'):
 
            test_uri = test_uri.rstrip(b'/') + b'/info/refs'
 

	
 
        url_obj.passwd = b'*****'
 
        cleaned_uri = str(url_obj)
 

	
 
        o = urllib.request.build_opener(*handlers)
 
        o.addheaders = [('User-Agent', 'git/1.7.8.0')]  # fake some git
 

	
 
        req = urllib.request.Request(
 
            "%s?%s" % (
kallithea/lib/vcs/backends/hg/repository.py
Show inline comments
 
@@ -25,25 +25,30 @@ import mercurial.hg
 
import mercurial.hgweb
 
import mercurial.httppeer
 
import mercurial.localrepo
 
import mercurial.match
 
import mercurial.mdiff
 
import mercurial.node
 
import mercurial.patch
 
import mercurial.scmutil
 
import mercurial.sshpeer
 
import mercurial.tags
 
import mercurial.ui
 
import mercurial.unionrepo
 
import mercurial.util
 

	
 

	
 
try:
 
    from mercurial.utils.urlutil import url as hg_url
 
except ImportError:  # urlutil was introduced in Mercurial 5.8
 
    from mercurial.util import url as hg_url
 

	
 
from kallithea.lib.vcs.backends.base import BaseRepository, CollectionGenerator
 
from kallithea.lib.vcs.exceptions import (BranchDoesNotExistError, ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, TagAlreadyExistError,
 
                                          TagDoesNotExistError, VCSError)
 
from kallithea.lib.vcs.utils import ascii_bytes, ascii_str, author_email, author_name, date_fromtimestamp, makedate, safe_bytes, safe_str
 
from kallithea.lib.vcs.utils.helpers import get_urllib_request_handlers
 
from kallithea.lib.vcs.utils.lazy import LazyProperty
 
from kallithea.lib.vcs.utils.paths import abspath
 

	
 
from . import changeset, inmemory, workdir
 

	
 

	
 
@@ -203,25 +208,25 @@ class MercurialRepository(BaseRepository
 

	
 
        :raises TagDoesNotExistError: if tag with given name does not exists
 
        """
 
        if name not in self.tags:
 
            raise TagDoesNotExistError("Tag %s does not exist" % name)
 
        if message is None:
 
            message = "Removed tag %s" % name
 
        if date is None:
 
            date = safe_bytes(datetime.datetime.now().strftime('%a, %d %b %Y %H:%M:%S'))
 
        local = False
 

	
 
        try:
 
            mercurial.tags.tag(self._repo, safe_bytes(name), mercurial.commands.nullid, safe_bytes(message), local, safe_bytes(user), date)
 
            mercurial.tags.tag(self._repo, safe_bytes(name), mercurial.node.nullid, safe_bytes(message), local, safe_bytes(user), date)
 
            self.tags = self._get_tags()
 
        except mercurial.error.Abort as e:
 
            raise RepositoryError(e.args[0])
 

	
 
    @LazyProperty
 
    def bookmarks(self):
 
        """
 
        Gets bookmarks for this repository
 
        """
 
        return self._get_bookmarks()
 

	
 
    def _get_bookmarks(self):
 
@@ -327,25 +332,25 @@ class MercurialRepository(BaseRepository
 

	
 
        url = safe_bytes(url)
 

	
 
        if parsed_url.scheme == 'ssh':
 
            # in case of invalid uri or authentication issues, sshpeer will
 
            # throw an exception.
 
            mercurial.sshpeer.instance(repoui or mercurial.ui.ui(), url, False).lookup(b'tip')
 
            return
 

	
 
        if '+' in parsed_url.scheme:  # strip 'git+' for hg-git URLs
 
            url = url.split(b'+', 1)[1]
 

	
 
        url_obj = mercurial.util.url(url)
 
        url_obj = hg_url(url)
 
        test_uri, handlers = get_urllib_request_handlers(url_obj)
 

	
 
        url_obj.passwd = b'*****'
 
        cleaned_uri = str(url_obj)
 

	
 
        o = urllib.request.build_opener(*handlers)
 
        o.addheaders = [('Content-Type', 'application/mercurial-0.1'),
 
                        ('Accept', 'application/mercurial-0.1')]
 

	
 
        req = urllib.request.Request(
 
            "%s?%s" % (
 
                safe_str(test_uri),
 
@@ -514,25 +519,25 @@ class MercurialRepository(BaseRepository
 

	
 
    def get_changesets(self, start=None, end=None, start_date=None,
 
                       end_date=None, branch_name=None, reverse=False, max_revisions=None):
 
        """
 
        Returns iterator of ``MercurialChangeset`` objects from start to end
 
        (both are inclusive)
 

	
 
        :param start: None, str, int or mercurial lookup format
 
        :param end:  None, str, int or mercurial lookup format
 
        :param start_date:
 
        :param end_date:
 
        :param branch_name:
 
        :param reversed: return changesets in reversed order
 
        :param reverse: return changesets in reversed order
 
        """
 
        start_raw_id = self._get_revision(start)
 
        start_pos = None if start is None else self.revisions.index(start_raw_id)
 
        end_raw_id = self._get_revision(end)
 
        end_pos = None if end is None else self.revisions.index(end_raw_id)
 

	
 
        if start_pos is not None and end_pos is not None and start_pos > end_pos:
 
            raise RepositoryError("Start revision '%s' cannot be "
 
                                  "after end revision '%s'" % (start, end))
 

	
 
        if branch_name and branch_name not in self.allbranches:
 
            msg = "Branch %r not found in %s" % (branch_name, self.name)
kallithea/lib/vcs/utils/helpers.py
Show inline comments
 
@@ -236,25 +236,25 @@ def get_dict_for_attrs(obj, attrs):
 
    data = {}
 
    for attr in attrs:
 
        data[attr] = getattr(obj, attr)
 
    return data
 

	
 
def get_urllib_request_handlers(url_obj):
 
    handlers = []
 
    test_uri, authinfo = url_obj.authinfo()
 

	
 
    if authinfo:
 
        # authinfo is a tuple (realm, uris, user, password) where 'uris' itself
 
        # is a tuple of URIs.
 
        # If url_obj is obtained via mercurial.util.url, the obtained authinfo
 
        # If url_obj is obtained via mercurial urlutil, the obtained authinfo
 
        # values will be bytes, e.g.
 
        #    (None, (b'http://127.0.0.1/repo', b'127.0.0.1'), b'user', b'pass')
 
        # However, urllib expects strings, not bytes, so we must convert them.
 

	
 
        # create a password manager
 
        passmgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
 
        passmgr.add_password(
 
            safe_str(authinfo[0]) if authinfo[0] else None, # realm
 
            tuple(safe_str(x) for x in authinfo[1]),        # uris
 
            safe_str(authinfo[2]),                          # user
 
            safe_str(authinfo[3]),                          # password
 
        )
kallithea/lib/webutils.py
Show inline comments
 
@@ -11,24 +11,25 @@
 
#
 
# You should have received a copy of the GNU General Public License
 
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
"""
 
kallithea.lib.webutils
 
~~~~~~~~~~~~~~~~~~~~~~
 

	
 
Helper functions that may rely on the current WSGI request, exposed in the TG2
 
thread-local "global" variables. It should have few dependencies so it can be
 
imported anywhere - just like the global variables can be used everywhere.
 
"""
 

	
 
import collections
 
import datetime
 
import json
 
import logging
 
import random
 
import re
 

	
 
from dateutil import relativedelta
 
from tg import request, session
 
from tg.i18n import ugettext as _
 
from tg.i18n import ungettext
 
from webhelpers2.html import HTML, escape, literal
 
from webhelpers2.html.tags import NotGiven, Option, Options, _input
 
@@ -57,24 +58,28 @@ assert format_byte_size
 
assert link_to
 
assert literal
 
assert password
 
assert radio
 
assert safeid
 
assert submit
 
assert text
 
assert textarea
 
assert truncate
 
assert wrap_paragraphs
 

	
 

	
 
# work around webhelpers2 being a dead project that doesn't support Python 3.10
 
collections.Sequence = collections.abc.Sequence
 

	
 

	
 
#
 
# General Kallithea URL handling
 
#
 

	
 
class UrlGenerator(object):
 
    """Emulate pylons.url in providing a wrapper around routes.url
 

	
 
    This code was added during migration from Pylons to Turbogears2. Pylons
 
    already provided a wrapper like this, but Turbogears2 does not.
 

	
 
    When the routing of Kallithea is changed to use less Routes and more
 
    Turbogears2-style routing, this class may disappear or change.
kallithea/model/scm.py
Show inline comments
 
@@ -704,24 +704,25 @@ class ScmModel(object):
 
                    log.warning('moving existing hook to %s', backup_file)
 
                    os.rename(hook_file, backup_file)
 
                try:
 
                    fh, fn = tempfile.mkstemp(prefix=hook_file + '.tmp.')
 
                    os.write(fh, tmpl.replace(b'_TMPL_', safe_bytes(kallithea.__version__)))
 
                    os.close(fh)
 
                    os.chmod(fn, 0o777 & ~umask)
 
                    os.rename(fn, hook_file)
 
                except (OSError, IOError) as e:
 
                    log.error('error writing hook %s: %s', hook_file, e)
 
            elif h_type == 'pre-receive':  # no longer used, so just remove any existing Kallithea hook
 
                if os.path.lexists(hook_file) and not other_hook:
 
                    log.warning('removing existing unused Kallithea hook %s', hook_file)
 
                    os.remove(hook_file)
 

	
 

	
 
def AvailableRepoGroupChoices(repo_group_perm_level, extras=()):
 
    """Return group_id,string tuples with choices for all the repo groups where
 
    the user has the necessary permissions.
 

	
 
    Top level is -1.
 
    """
 
    groups = db.RepoGroup.query().all()
 
    if HasPermissionAny('hg.admin')('available repo groups'):
 
        groups.append(None)
kallithea/public/js/base.js
Show inline comments
 
@@ -668,32 +668,34 @@ function _comment_div_append_form($comme
 
        }
 
        function failure(x, s, e) {
 
            $preview.removeClass('submitting').children('.panel').addClass('panel-danger');
 
            var $status = $preview.find('.comment-submission-status');
 
            $('<span>', {
 
                'title': e,
 
                text: _TM['Unable to post']
 
            }).replaceAll($status.contents());
 
            $('<div>', {
 
                'class': 'btn-group'
 
            }).append(
 
                $('<button>', {
 
                    'type': 'button',
 
                    'class': 'btn btn-default btn-xs',
 
                    text: _TM['Retry']
 
                }).click(function() {
 
                    $status.text(_TM['Submitting ...']);
 
                    $preview.addClass('submitting').children('.panel').removeClass('panel-danger');
 
                    ajaxPOST(AJAX_COMMENT_URL, postData, success, failure);
 
                }),
 
                $('<button>', {
 
                    'type': 'button',
 
                    'class': 'btn btn-default btn-xs',
 
                    text: _TM['Cancel']
 
                }).click(function() {
 
                    comment_div_state($comment_div, f_path, line_no);
 
                })
 
            ).appendTo($status);
 
        }
 
        ajaxPOST(AJAX_COMMENT_URL, postData, success, failure);
 
    });
 

	
 
    // add event handler for hide/cancel buttons
 
    $form.find('.hide-inline-form').click(function() {
kallithea/templates/admin/repo_groups/repo_group_edit_perms.html
Show inline comments
 
${h.form(url('edit_repo_group_perms', group_name=c.repo_group.group_name))}
 
<div class="form">
 
    <div>
 
        <div>
 
            <table id="permissions_manage" class="table">
 
                <tr>
 
                    <td>${_('None')}<br />(${_('Not visible')})</td>
 
                    <td>${_('Read')}<br />(${_('Visible')})</td>
 
                    <td>${_('Write')}<br />(${_('Add repos')})</td>
 
                    <td>${_('Admin')}<br />(${_('Add/Edit groups')})</td>
 
                    <td>${_('User/User Group')}</td>
 
                    <td></td>
 
                </tr>
 
                ## USERS
 
                %for r2p in c.repo_group.repo_group_to_perm:
 
                    ##forbid revoking permission from yourself, except if you're an super admin
 
@@ -90,25 +89,24 @@ ${h.form(url('edit_repo_group_perms', gr
 
                       ${h.radio('recursive', 'repos', label=_('Repositories'))}
 
                       ${h.radio('recursive', 'all', label=_('Both'))}
 
                       <span class="help-block">${_('Set or revoke permission to all children of that group, including non-private repositories and other groups if selected.')}</span>
 
                    </td>
 
                </tr>
 
            </table>
 
        </div>
 
        <div class="buttons">
 
            ${h.submit('save',_('Save'),class_="btn btn-default")}
 
            ${h.reset('reset',_('Reset'),class_="btn btn-default")}
 
        </div>
 
    </div>
 
</div>
 
${h.end_form()}
 

	
 
<script>
 
    'use strict';
 
    function ajaxActionRevoke(obj_id, obj_type, field_id, obj_name) {
 
        let url = ${h.jshtml(h.url('edit_repo_group_perms_delete', group_name=c.repo_group.group_name))};
 
        var revoke_msg = _TM['Confirm to revoke permission for {0}: {1}?'].format(obj_type.replace('_', ' '), obj_name);
 
        if (confirm(revoke_msg)){
 
            var recursive = $('input[name=recursive]:checked').val();
 
            ajaxActionRevokePermission(url, obj_id, obj_type, field_id, {recursive:recursive});
 
        }
 
    }
kallithea/templates/admin/repos/repo_edit_permissions.html
Show inline comments
 
@@ -48,48 +48,50 @@ ${h.form(url('edit_repo_perms_update', r
 
                %endfor
 

	
 
                ## USER GROUPS
 
                %for g2p in sorted(c.repo_info.users_group_to_perm, key=lambda x:x.users_group.users_group_name):
 
                    <tr id="id${id(g2p.users_group.users_group_name)}">
 
                        <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.none')}</td>
 
                        <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.read')}</td>
 
                        <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.write')}</td>
 
                        <td>${h.radio('g_perm_%s' % g2p.users_group.users_group_name,'repository.admin')}</td>
 
                        <td>
 
                            <i class="icon-users"></i>
 
                            %if h.HasPermissionAny('hg.admin')():
 
                             <a href="${h.url('edit_users_group',id=g2p.users_group.users_group_id)}">${g2p.users_group.users_group_name}</a>
 
                             <a href="${h.url('edit_users_group',id=g2p.users_group.users_group_id)}">
 
                                 ${g2p.users_group.users_group_name}
 
                             </a>
 
                            %else:
 
                             ${g2p.users_group.users_group_name}
 
                            %endif
 
                        </td>
 
                        <td>
 
                            <button type="button" class="btn btn-default btn-xs" onclick="ajaxActionRevoke(${g2p.users_group.users_group_id}, 'user_group', '${'id%s'%id(g2p.users_group.users_group_name)}', '${g2p.users_group.users_group_name}')">
 
                            <i class="icon-minus-circled"></i>${_('Revoke')}
 
                            </button>
 
                        </td>
 
                    </tr>
 
                %endfor
 
                ## New entries added by addPermAction here.
 
                <tr class="new_members last_new_member" id="add_perm_input"><td colspan="6"></td></tr>
 
                <tr>
 
                    <td colspan="6">
 
                        <button type="button" id="add_perm" class="btn btn-link btn-xs">
 
                            <i class="icon-plus"></i>${_('Add new')}
 
                        </button>
 
                    </td>
 
                </tr>
 
            </table>
 
        </div>
 
        <div class="form-group">
 
        <div class="buttons">
 
            ${h.submit('save',_('Save'),class_="btn btn-default")}
 
            ${h.reset('reset',_('Reset'),class_="btn btn-default")}
 
        </div>
 
</div>
 
${h.end_form()}
 

	
 
<script>
 
    'use strict';
 
    function ajaxActionRevoke(obj_id, obj_type, field_id, obj_name) {
 
        let url = ${h.js(h.url('edit_repo_perms_revoke',repo_name=c.repo_name))};
 
        var revoke_msg = _TM['Confirm to revoke permission for {0}: {1}?'].format(obj_type.replace('_', ' '), obj_name);
 
        if (confirm(revoke_msg)){
kallithea/templates/admin/user_groups/user_group_edit_perms.html
Show inline comments
 
${h.form(url('edit_user_group_perms_update', id=c.user_group.users_group_id))}
 
<div class="form">
 
   <div>
 
        <div>
 
            <table id="permissions_manage" class="table">
 
                <tr>
 
                    <td>${_('None')}</td>
 
                    <td>${_('Read')}</td>
 
                    <td>${_('Write')}</td>
 
                    <td>${_('Admin')}</td>
 
                    <td>${_('User/User Group')}</td>
 
                    <td></td>
 
                </tr>
 
                ## USERS
 
                %for r2p in c.user_group.user_user_group_to_perm:
 
                    ##forbid revoking permission from yourself, except if you're an super admin
 
@@ -58,47 +57,46 @@ ${h.form(url('edit_user_group_perms_upda
 
                        <td>${h.radio('g_perm_%s' % g2p.user_group.users_group_name,'usergroup.admin')}</td>
 
                        <td>
 
                            <i class="icon-users"></i>
 
                            %if h.HasPermissionAny('hg.admin')():
 
                             <a href="${h.url('edit_users_group',id=g2p.user_group.users_group_id)}">
 
                                 ${g2p.user_group.users_group_name}
 
                             </a>
 
                            %else:
 
                             ${g2p.user_group.users_group_name}
 
                            %endif
 
                        </td>
 
                        <td>
 
                            <button class="btn btn-default btn-xs" onclick="ajaxActionRevoke(${g2p.user_group.users_group_id}, 'user_group', '${'id%s'%id(g2p.user_group.users_group_name)}', '${g2p.user_group.users_group_name}')">
 
                            <button type="button" class="btn btn-default btn-xs" onclick="ajaxActionRevoke(${g2p.user_group.users_group_id}, 'user_group', '${'id%s'%id(g2p.user_group.users_group_name)}', '${g2p.user_group.users_group_name}')">
 
                            <i class="icon-minus-circled"></i>${_('Revoke')}
 
                            </button>
 
                        </td>
 
                    </tr>
 
                %endfor
 
                ## New entries added by addPermAction here.
 
                <tr class="new_members last_new_member" id="add_perm_input"><td colspan="6"></td></tr>
 
                <tr>
 
                    <td colspan="6">
 
                        <button id="add_perm" class="btn btn-link btn-xs">
 
                        <button type="button" id="add_perm" class="btn btn-link btn-xs">
 
                            <i class="icon-plus"></i>${_('Add new')}
 
                        </button>
 
                    </td>
 
                </tr>
 
            </table>
 
        </div>
 
        <div class="buttons">
 
            ${h.submit('save',_('Save'),class_="btn btn-default")}
 
            ${h.reset('reset',_('Reset'),class_="btn btn-default")}
 
        </div>
 
   </div>
 
</div>
 
${h.end_form()}
 

	
 
<script>
 
    'use strict';
 
    function ajaxActionRevoke(obj_id, obj_type, field_id, obj_name) {
 
        let url = ${h.js(h.url('edit_user_group_perms_delete', id=c.user_group.users_group_id))};
 
        var revoke_msg = _TM['Confirm to revoke permission for {0}: {1}?'].format(obj_type.replace('_', ' '), obj_name);
 
        if (confirm(revoke_msg)){
 
            ajaxActionRevokePermission(url, obj_id, obj_type, field_id);
 
        }
 
    }
 

	
kallithea/templates/base/base.html
Show inline comments
 
@@ -14,25 +14,25 @@
 
<div class="footer navbar navbar-inverse">
 
    <span class="navbar-text pull-left">
 
        ${_('Server instance: %s') % c.instance_id if c.instance_id else ''}
 
    </span>
 
    <span class="navbar-text pull-right">
 
        This site is powered by
 
        %if c.visual.show_version:
 
            <a class="navbar-link" href="${h.url('kallithea_project_url')}" target="_blank">Kallithea</a> ${c.kallithea_version},
 
        %else:
 
            <a class="navbar-link" href="${h.url('kallithea_project_url')}" target="_blank">Kallithea</a>,
 
        %endif
 
        which is
 
        <a class="navbar-link" href="${h.canonical_url('about')}#copyright">&copy; 2010&ndash;2021 by various authors &amp; licensed under GPLv3</a>.
 
        <a class="navbar-link" href="${h.canonical_url('about')}#copyright">&copy; 2010&ndash;2022 by various authors &amp; licensed under GPLv3</a>.
 
        %if c.issues_url:
 
            &ndash; <a class="navbar-link" href="${c.issues_url}" target="_blank">${_('Support')}</a>
 
        %endif
 
    </span>
 
</div>
 

	
 
<!-- END FOOTER -->
 

	
 
### MAKO DEFS ###
 

	
 
<%block name="branding_title">
 
    %if c.site_name:
kallithea/templates/changeset/diff_block.html
Show inline comments
 
## -*- coding: utf-8 -*-
 

	
 
<%def name="diff_block(a_repo_name, a_ref_type, a_ref_name, a_rev,
 
                       cs_repo_name, cs_ref_name, cs_ref_type, cs_rev,
 
                       file_diff_data)">
 
<div class="diff-collapse">
 
    <button data-target="${'diff-container-%s' % (id(file_diff_data))}" class="diff-collapse-button btn btn-link btn-sm">&uarr; ${_('Collapse Diff')} &uarr;</button>
 
    <button type='button', data-target="${'diff-container-%s' % (id(file_diff_data))}" class="diff-collapse-button btn btn-link btn-sm">&uarr; ${_('Collapse Diff')} &uarr;</button>
 
</div>
 
%for id_fid, url_fid, op, a_filename, cs_filename, diff, stats in file_diff_data:
 
    ${diff_block_diffblock(id_fid, url_fid, op, diff,
 
        a_repo_name, a_rev, a_ref_type, a_ref_name, a_filename,
 
        cs_repo_name, cs_rev, cs_ref_type, cs_ref_name, cs_filename,
 
        'diff-container-%s' % id(file_diff_data))}
 
%endfor
 
</%def>
 

	
 
<%def name="diff_block_diffblock(id_fid, url_fid, op, diff,
 
    a_repo_name, a_rev, a_ref_type, a_ref_name, a_filename,
 
    cs_repo_name, cs_rev, cs_ref_type, cs_ref_name, cs_filename, cls)"
kallithea/templates/data_table/_dt_elements.html
Show inline comments
 
@@ -61,78 +61,78 @@
 
  %if request.authuser.username != 'default':
 
    <a title="${_('Subscribe to %s atom feed')% name}" href="${webutils.url('atom_feed_home',repo_name=name,api_key=request.authuser.api_key)}"><i class="icon-rss-squared"></i></a>
 
  %else:
 
    <a title="${_('Subscribe to %s atom feed')% name}" href="${webutils.url('atom_feed_home',repo_name=name)}"><i class="icon-rss-squared"></i></a>
 
  %endif
 
</%def>
 

	
 
<%def name="repo_actions(repo_name)">
 
      <a href="${webutils.url('edit_repo',repo_name=repo_name)}" title="${_('Edit')}" class="btn btn-default btn-xs">
 
        <i class="icon-pencil"></i>${_('Edit')}
 
      </a>
 
      ${webutils.form(webutils.url('delete_repo', repo_name=repo_name))}
 
        <button name="${'remove_%s' % repo_name}" class="btn btn-default btn-xs"
 
        <button type="submit" name="${'remove_%s' % repo_name}" class="btn btn-default btn-xs"
 
            onclick="return confirm('${_('Confirm to delete this repository: %s') % repo_name}');">
 
          <i class="icon-trashcan"></i>${_('Delete')}
 
        </button>
 
      ${webutils.end_form()}
 
</%def>
 

	
 
<%def name="repo_state(repo_state)">
 
    %if repo_state == u'repo_state_pending':
 
        <div class="label label-info">${_('Creating')}</div>
 
    %elif repo_state == u'repo_state_created':
 
        <div class="label label-success">${_('Created')}</div>
 
    %else:
 
        <div class="label label-danger" title="${repo_state}">invalid</div>
 
    %endif
 
</%def>
 

	
 
<%def name="user_actions(user_id, username)">
 
   <a href="${webutils.url('edit_user',id=user_id)}" title="${_('Edit')}" class="btn btn-default btn-xs">
 
     <i class="icon-pencil"></i>${_('Edit')}
 
   </a>
 
  ${webutils.form(webutils.url('delete_user', id=user_id))}
 
    <button id="${'remove_user_%s' % user_id}" name="${'remove_user_%s' % repo_name}" class="btn btn-default btn-xs" title="${_('Delete')}"
 
    <button type="submit" id="${'remove_user_%s' % user_id}" name="${'remove_user_%s' % repo_name}" class="btn btn-default btn-xs" title="${_('Delete')}"
 
        onclick="return confirm('${_('Confirm to delete this user: %s') % username}');">
 
      <i class="icon-trashcan"></i>${_('Delete')}
 
    </button>
 
  ${webutils.end_form()}
 
</%def>
 

	
 
<%def name="user_group_actions(user_group_id, user_group_name)">
 
    <a href="${webutils.url('edit_users_group', id=user_group_id)}" title="${_('Edit')}" class="btn btn-default btn-xs">
 
      <i class="icon-pencil"></i>${_('Edit')}
 
    </a>
 
    ${webutils.form(webutils.url('delete_users_group', id=user_group_id))}
 
      <button id="${'remove_group_%s' % user_group_id}" name="${'remove_user_%s' % repo_name}" class="btn btn-default btn-xs" title="${_('Delete')}"
 
      <button type="submit" id="${'remove_group_%s' % user_group_id}" name="${'remove_user_%s' % repo_name}" class="btn btn-default btn-xs" title="${_('Delete')}"
 
          onclick="return confirm('${_('Confirm to delete this user group: %s') % user_group_name}');">
 
        <i class="icon-trashcan"></i>${_('Delete')}
 
      </button>
 
    ${webutils.end_form()}
 
</%def>
 

	
 
<%def name="group_name_html(group_name,name)">
 
  <div class="dt_repo">
 
    <i class="icon-folder"></i>
 
    <a href="${webutils.url('repos_group_home',group_name=group_name)}">${name}</a>
 
  </div>
 
</%def>
 

	
 
<%def name="repo_group_actions(repo_group_id, repo_group_name, gr_count)">
 
    <a href="${webutils.url('edit_repo_group',group_name=repo_group_name)}" title="${_('Edit')}" class="btn btn-default btn-xs">
 
      <i class="icon-pencil"></i>${_('Edit')}
 
    </a>
 
    ${webutils.form(webutils.url('delete_repo_group', group_name=repo_group_name))}
 
      <button id="${'remove_%s' % repo_group_name}" name="${'remove_%s' % repo_group_name}" class="btn btn-default btn-xs" title="${_('Delete')}"
 
      <button type="submit" id="${'remove_%s' % repo_group_name}" name="${'remove_%s' % repo_group_name}" class="btn btn-default btn-xs" title="${_('Delete')}"
 
          onclick="return confirm('${ungettext('Confirm to delete this group: %s with %s repository','Confirm to delete this group: %s with %s repositories',gr_count) % (repo_group_name, gr_count)}')">
 
        <i class="icon-trashcan"></i>${_('Delete')}
 
      </button>
 
    ${webutils.end_form()}
 
</%def>
 

	
 
<%def name="user_name(user_id, username)">
 
    ${webutils.link_to(username,webutils.url('edit_user', id=user_id))}
 
</%def>
 

	
 
<%def name="repo_group_name(repo_group_name, children_groups)">
 
  <div class="text-nowrap">
kallithea/tests/functional/test_admin_repo_groups.py
Show inline comments
 
from kallithea.model import meta
 
from kallithea.model import db, meta
 
from kallithea.model.repo_group import RepoGroupModel
 
from kallithea.tests.base import TestController, url
 
from kallithea.tests import base
 
from kallithea.tests.fixture import Fixture
 

	
 

	
 
fixture = Fixture()
 

	
 

	
 
class TestRepoGroupsController(TestController):
 
class TestRepoGroupsController(base.TestController):
 

	
 
    def test_index(self):
 
        self.log_user()
 
        response = self.app.get(base.url('repos_groups'))
 
        response.mustcontain('"records": []')
 

	
 
    def test_new(self):
 
        self.log_user()
 
        response = self.app.get(base.url('new_repos_group'))
 

	
 
    def test_create(self):
 
        self.log_user()
 

	
 
        group_name = 'foo'
 

	
 
        # creation with form error
 
        response = self.app.post(base.url('repos_groups'),
 
                                         {'group_name': group_name,
 
                                          '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
        response.mustcontain('name="group_name" type="text" value="%s"' % group_name)
 
        response.mustcontain('<!-- for: group_description -->')
 

	
 
        # creation
 
        response = self.app.post(base.url('repos_groups'),
 
                                         {'group_name': group_name,
 
                                         'group_description': 'lala',
 
                                         'parent_group_id': '-1',
 
                                         'group_copy_permissions': 'True',
 
                                          '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
        self.checkSessionFlash(response, 'Created repository group %s' % group_name)
 

	
 
        # edit form
 
        response = self.app.get(base.url('edit_repo_group', group_name=group_name))
 
        response.mustcontain('>lala<')
 

	
 
        # edit with form error
 
        response = self.app.post(base.url('update_repos_group', group_name=group_name),
 
                                         {'group_name': group_name,
 
                                          '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
        response.mustcontain('name="group_name" type="text" value="%s"' % group_name)
 
        response.mustcontain('<!-- for: group_description -->')
 

	
 
        # edit
 
        response = self.app.post(base.url('update_repos_group', group_name=group_name),
 
                                         {'group_name': group_name,
 
                                         'group_description': 'lolo',
 
                                          '_session_csrf_secret_token': self.session_csrf_secret_token()})
 
        self.checkSessionFlash(response, 'Updated repository group %s' % group_name)
 
        response = response.follow()
 
        response.mustcontain('name="group_name" type="text" value="%s"' % group_name)
 
        response.mustcontain(no='<!-- for: group_description -->')
 
        response.mustcontain('>lolo<')
 

	
 
        # listing
 
        response = self.app.get(base.url('repos_groups'))
 
        response.mustcontain('raw_name": "%s"' % group_name)
 

	
 
        # show
 
        response = self.app.get(base.url('repos_group', group_name=group_name))
 
        response.mustcontain('href="/_admin/repo_groups/%s/edit"' % group_name)
 

	
 
        # show ignores extra trailing slashes in the URL
 
        response = self.app.get(base.url('repos_group', group_name='%s//' % group_name))
 
        response.mustcontain('href="/_admin/repo_groups/%s/edit"' % group_name)
 

	
 
        # delete
 
        response = self.app.post(base.url('delete_repo_group', group_name=group_name),
 
                                 {'_session_csrf_secret_token': self.session_csrf_secret_token()})
 
        self.checkSessionFlash(response, 'Removed repository group %s' % group_name)
 

	
 
    def test_new_by_regular_user(self):
 
        self.log_user(base.TEST_USER_REGULAR_LOGIN, base.TEST_USER_REGULAR_PASS)
 
        response = self.app.get(base.url('new_repos_group'), status=403)
 

	
 
    def test_case_insensitivity(self):
 
        self.log_user()
 
        group_name = 'newgroup'
 
        response = self.app.post(url('repos_groups'),
 
        response = self.app.post(base.url('repos_groups'),
 
                                 fixture._get_repo_group_create_params(group_name=group_name,
 
                                                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
 
        # try to create repo group with swapped case
 
        swapped_group_name = group_name.swapcase()
 
        response = self.app.post(url('repos_groups'),
 
        response = self.app.post(base.url('repos_groups'),
 
                                 fixture._get_repo_group_create_params(group_name=swapped_group_name,
 
                                                                 _session_csrf_secret_token=self.session_csrf_secret_token()))
 
        response.mustcontain('already exists')
 

	
 
        RepoGroupModel().delete(group_name)
 
        meta.Session().commit()
 

	
 
    def test_subgroup_deletion(self):
 
        self.log_user()
 
        parent = None
 
        parent_name = 'parent'
 
        sub = None
 
        sub_name = 'sub'
 
        sub_path = 'parent/sub'
 

	
 
        try:
 
            # create parent group
 
            assert db.RepoGroup.guess_instance(parent_name) is None
 
            response = self.app.post(
 
                base.url('repos_groups'),
 
                fixture._get_repo_group_create_params(
 
                    group_name=parent_name,
 
                    _session_csrf_secret_token=self.session_csrf_secret_token()
 
                )
 
            )
 
            parent = db.RepoGroup.guess_instance(parent_name)
 
            assert parent is not None
 

	
 
            # create sub group
 
            assert db.RepoGroup.guess_instance(sub_path) is None
 
            response = self.app.post(
 
                base.url('repos_groups'),
 
                fixture._get_repo_group_create_params(
 
                    group_name=sub_name,
 
                    parent_group_id=parent.group_id,
 
                    _session_csrf_secret_token=self.session_csrf_secret_token()
 
                )
 
            )
 
            sub = db.RepoGroup.guess_instance(sub_path)
 
            assert sub is not None
 

	
 
            # delete sub group
 
            response = self.app.post(
 
                base.url('delete_repo_group', group_name=sub_path),
 
                params={
 
                    '_session_csrf_secret_token': self.session_csrf_secret_token()
 
                },
 
            )
 
            sub = db.RepoGroup.guess_instance(sub_path)
 
            assert sub is None
 

	
 
        finally:
 
            if sub:
 
                RepoGroupModel().delete(sub)
 
            if parent:
 
                RepoGroupModel().delete(parent)
 
            meta.Session().commit()
kallithea/tests/functional/test_repo_groups.py
Show inline comments
 
deleted file
setup.py
Show inline comments
 
@@ -41,41 +41,41 @@ __platform__ = platform.system()
 
is_windows = __platform__ in ['Windows']
 

	
 
requirements = [
 
    "alembic >= 1.0.10, < 1.5",
 
    "gearbox >= 0.1.0, < 1",
 
    "waitress >= 0.8.8, < 1.5",
 
    "WebOb >= 1.8, < 1.9",
 
    "backlash >= 0.1.2, < 1",
 
    "TurboGears2 >= 2.4, < 2.5",
 
    "tgext.routes >= 0.2.0, < 1",
 
    "Beaker >= 1.10.1, < 2",
 
    "WebHelpers2 >= 2.0, < 2.1",
 
    "FormEncode >= 1.3.1, < 1.4",
 
    "FormEncode >= 1.3.1, < 2.1",
 
    "SQLAlchemy >= 1.2.9, < 1.4",
 
    "Mako >= 0.9.1, < 1.2",
 
    "Pygments >= 2.2.0, < 2.7",
 
    "Whoosh >= 2.7.1, < 2.8",
 
    "celery >= 5, < 5.1",
 
    "Babel >= 1.3, < 2.9",
 
    "python-dateutil >= 2.1.0, < 2.9",
 
    "Markdown >= 2.2.1, < 3.2",
 
    "docutils >= 0.11, < 0.17",
 
    "URLObject >= 2.3.4, < 2.5",
 
    "Routes >= 2.0, < 2.5",
 
    "dulwich >= 0.19.0, < 0.20",
 
    "mercurial >= 5.2, < 5.9",
 
    "mercurial >= 5.2, < 6.2",
 
    "decorator >= 4.2.1, < 4.5",
 
    "Paste >= 2.0.3, < 3.5",
 
    "bleach >= 3.0, < 3.1.4",
 
    "bleach >= 3.2, < 4.2",
 
    "Click >= 7.0, < 8",
 
    "ipaddr >= 2.2.0, < 2.3",
 
    "paginate >= 0.5, < 0.6",
 
    "paginate_sqlalchemy >= 0.3.0, < 0.4",
 
    "bcrypt >= 3.1.0, < 3.2",
 
    "pip >= 20.0, < 999",
 
    "chardet >= 3",
 
]
 

	
 
dependency_links = [
 
]
 

	
0 comments (0 inline, 0 general)