diff --git a/.dockerignore b/.dockerignore index 33331455525..f7d90d4e531 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,22 @@ .hg + +# Remove the git objects, logs, etc. to make final image smaller. +# Some files still need to be in the .git directory, because Etherpad at +# startup uses them to discover its version number. +.git/branches +.git/COMMIT_EDITMSG +.git/config +.git/description +.git/FETCH_HEAD +.git/hooks +.git/index +.git/info +.git/logs +.git/objects +.git/ORIG_HEAD +.git/packed-refs +.git/refs/remotes/ +.gitignore + settings.json src/node_modules diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000000..4906ca04fc2 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,46 @@ +* * * + +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: + +* * * + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Environment (please complete the following information):** + +- Etherpad Version: (e.g. 1.8.0) +- Deployment (manual install, docker, ...) + +**Desktop (please complete the following information):** + +- OS: (e.g. iOS) +- Browser (e.g. chrome, safari) +- Version (e.g. 22) + +**Smartphone (please complete the following information):** + +- Device: (e.g. iPhone6) +- OS: (e.g. iOS8.1) +- Browser (e.g. stock browser, safari) +- Version (e.g. 22) + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000000..41867e2701a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,21 @@ +* * * + +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: + +* * * + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when (...) + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000000..d745034b460 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,29 @@ + + +> Please provide enough information so that others can review your pull request: + + + +> Explain the **details** for making this change. What existing problem does the pull request solve? + + + +> Screenshots/GIFs + + diff --git a/.gitignore b/.gitignore index 625f153d769..95aed121feb 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,6 @@ npm-debug.log bin/etherpad-1.deb credentials.json out/ +.nyc_output +./package-lock.json +.idea diff --git a/.travis.yml b/.travis.yml index 72ae8027b2f..6b3bb6c7c78 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,18 +1,49 @@ language: node_js + node_js: - "lts/*" + +services: + - docker + install: - "bin/installDeps.sh" - "export GIT_HASH=$(git rev-parse --verify --short HEAD)" - "npm install ep_test_line_attrib" + +before_script: + - "tests/frontend/travis/sauce_tunnel.sh" + script: - "tests/frontend/travis/runner.sh" + env: global: - secure: "WMGxFkOeTTlhWB+ChMucRtIqVmMbwzYdNHuHQjKCcj8HBEPdZLfCuK/kf4rG\nVLcLQiIsyllqzNhBGVHG1nyqWr0/LTm8JRqSCDDVIhpyzp9KpCJQQJG2Uwjk\n6/HIJJh/wbxsEdLNV2crYU/EiVO3A4Bq0YTHUlbhUqG3mSCr5Ec=" - secure: "gejXUAHYscbR6Bodw35XexpToqWkv2ifeECsbeEmjaLkYzXmUUNWJGknKSu7\nEUsSfQV8w+hxApr1Z+jNqk9aX3K1I4btL3cwk2trnNI8XRAvu1c1Iv60eerI\nkE82Rsd5lwUaMEh+/HoL8ztFCZamVndoNgX7HWp5J/NRZZMmh4g=" -jdk: - - oraclejdk6 + +jobs: + include: + - name: "Run the Backend tests" + install: + - "cd src && npm install && cd -" + script: + - "tests/frontend/travis/runnerBackend.sh" + - name: "Test the Frontend" + install: + - "bin/installDeps.sh" + - "export GIT_HASH=$(git rev-parse --verify --short HEAD)" + - "npm install ep_test_line_attrib" + script: + - "tests/frontend/travis/runner.sh" + - name: "Test the Dockerfile" + install: + - "cd src && npm install && cd -" + script: + - "docker build -t etherpad:test ." + - "docker run -d -p 9001:9001 etherpad:test && sleep 3" + - "cd src && npm run test-container" + notifications: irc: channels: diff --git a/CHANGELOG.md b/CHANGELOG.md index 618a88e1023..3ea6cde7cfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,29 @@ +# 1.8.3 +* FEATURE: colibris is now the default skin for new installs +* FEATURE: improved colibris visuals, and migrated to Flexbox layout +* FEATURE: skin variants: colibris skin colors can be easily customized. Visit http://127.0.0.1:9001/p/test#skinvariantsbuilder +* REQUIREMENTS: minimum required Node version is **10.13.0 LTS**. +* MINOR: stability fixes for the async migration in 1.8.0 (fixed many UnhandledPromiseRejectionWarning and the few remaining crashes) +* MINOR: improved stability of import/export functionality +* MINOR: fixed many small UI quirks (timeslider, import/export, chat) +* MINOR: Docker images are now built & run in production mode by default +* MINOR: reduced the size of the Docker images +* MINOR: better documented cookies and configuration parameters of the Docker image +* MINOR: better database support (especially MySQL) +* MINOR: additional test coverage +* MINOR: restored compatibility with ep_hash_auth +* MINOR: migrate from swagger-node-express to openapi-backend +* MINOR: honor the Accept-Language HTTP headers sent by browsers, eventually serving language variants +* PERFORMANCE: correctly send HTTP/304 for minified files +* SECURITY: bumped many dependencies. At the time of the release, this version has 0 reported vulnerabilities by npm audit +* SECURITY: never send referrer when opening a link +* SECURITY: rate limit imports and exports +* SECURITY: do not allow pad import if a user never contributed to that pad +* SECURITY: expose configuration parameter for limiting max import size + +*BREAKING CHANGE*: undoing the "clear authorship colors" command is no longer supported (see https://github.com/ether/etherpad-lite/issues/2802) +*BREAKING CHANGE*: the visuals and CSS structure of the page was updated. Plugins may need a CSS rehaul + # 1.8 * SECURITY: change referrer policy so that Etherpad addresses aren't leaked when links are clicked (discussion: https://github.com/ether/etherpad-lite/pull/3636) * SECURITY: set the "secure" flag for the session cookies when served over SSL. From now on it will not be possible to serve the same instance both in cleartext and over SSL diff --git a/Dockerfile b/Dockerfile index 50996126175..6e6a7c7d407 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,9 +15,10 @@ LABEL maintainer="Etherpad team, https://github.com/ether/etherpad-lite" # ETHERPAD_PLUGINS="ep_codepad ep_author_neat" ARG ETHERPAD_PLUGINS= -# Set the following to production to avoid installing devDeps -# this can be done with build args (and is mandatory to build ARM version) -ENV NODE_ENV=development +# By default, Etherpad container is built and run in "production" mode. This is +# leaner (development dependencies are not installed) and runs faster (among +# other things, assets are minified & compressed). +ENV NODE_ENV=production # Follow the principle of least privilege: run as unprivileged user. # @@ -25,13 +26,13 @@ ENV NODE_ENV=development # that do not allow images running as root. RUN useradd --uid 5001 --create-home etherpad -RUN mkdir /opt/etherpad-lite && chown etherpad:etherpad /opt/etherpad-lite +RUN mkdir /opt/etherpad-lite && chown etherpad:0 /opt/etherpad-lite -USER etherpad:etherpad +USER etherpad WORKDIR /opt/etherpad-lite -COPY --chown=etherpad:etherpad ./ ./ +COPY --chown=etherpad:0 ./ ./ # install node dependencies for Etherpad RUN bin/installDeps.sh && \ @@ -44,7 +45,10 @@ RUN bin/installDeps.sh && \ RUN for PLUGIN_NAME in ${ETHERPAD_PLUGINS}; do npm install "${PLUGIN_NAME}"; done # Copy the configuration file. -COPY --chown=etherpad:etherpad ./settings.json.docker /opt/etherpad-lite/settings.json +COPY --chown=etherpad:0 ./settings.json.docker /opt/etherpad-lite/settings.json + +# Fix permissions for root group +RUN chmod -R g=u . EXPOSE 9001 CMD ["node", "node_modules/ep_etherpad-lite/node/server.js"] diff --git a/Makefile b/Makefile index aedb9372492..0c99d9ff481 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,14 @@ docassets = $(addprefix out/,$(wildcard doc/assets/*)) VERSION = $(shell node -e "console.log( require('./src/package.json').version )") UNAME := $(shell uname -s) -docs: $(outdoc_files) $(docassets) +ensure_marked_is_installed: + set -eu; \ + hash npm; \ + if [ $(shell npm list --prefix bin/doc >/dev/null 2>/dev/null; echo $$?) -ne "0" ]; then \ + npm ci --prefix=bin/doc; \ + fi + +docs: ensure_marked_is_installed $(outdoc_files) $(docassets) out/doc/assets/%: doc/assets/% mkdir -p $(@D) diff --git a/README.md b/README.md index 28b94d85e3b..5af71ef3c05 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,17 @@ # A real-time collaborative editor for the web Docker Pulls -![Demo Etherpad Animated Jif](https://i.imgur.com/zYrGkg3.gif "Etherpad in action") +[![Travis (.org)](https://img.shields.io/travis/ether/etherpad-lite)](https://travis-ci.org/github/ether/etherpad-lite) +![Demo Etherpad Animated Jif](doc/images/etherpad_demo.gif "Etherpad in action") # About Etherpad is a real-time collaborative editor scalable to thousands of simultaneous real time users. It provides full data export capabilities, and runs on _your_ server, under _your_ control. -**[Try it out](https://beta.etherpad.org)** +**[Try it out](https://video.etherpad.com)** # Installation ## Requirements -- `nodejs` >= **8.9.0** (preferred: `nodejs` >= **10.13.0**). Please note that starting Jan 1st, 2020, nodejs 8.x is deprecated. +- `nodejs` >= **10.13.0**. ## GNU/Linux and other UNIX-like systems @@ -22,7 +23,7 @@ git clone --branch master https://github.com/ether/etherpad-lite.git && cd ether ``` ### Manual install -You'll need git and [node.js](https://nodejs.org) installed (minimum required Node version: **8.9.0**, preferred: >= **10.13.0**). +You'll need git and [node.js](https://nodejs.org) installed (minimum required Node version: **10.13.0**). **As any user (we recommend creating a separate user called etherpad):** @@ -50,7 +51,7 @@ You'll need [node.js](https://nodejs.org) and (optionally, though recommended) g 1. Grab the source, either - download - or `git clone --branch master https://github.com/ether/etherpad-lite.git` -2. start `bin\installOnWindows.bat` +2. With a "Run as administrator" command prompt execute `bin\installOnWindows.bat` Now, run `start.bat` and open in your browser. @@ -83,10 +84,20 @@ If you have enabled authentication in `users` section in `settings.json`, it is Please install [ep_hash_auth plugin](https://www.npmjs.com/package/ep_hash_auth) and configure it. If you prefer, `ep_hash_auth` also gives you the option of storing the users in a custom directory in the file system, without having to edit `settings.json` and restart Etherpad each time. -## Plugins and themes +## Customize functionalities with plugins + +![Basic install](doc/images/etherpad_basic.png "Basic Installation") + +![Full Features](doc/images/etherpad_full_features.png "You can add a lot of plugins !") Etherpad is very customizable through plugins. Instructions for installing themes and plugins can be found in [the plugin wiki article](https://github.com/ether/etherpad-lite/wiki/Available-Plugins). +## Customize the style with skin variants + +Open in your browser and start playing ! + +![Skin Variant](doc/images/etherpad_skin_variants.gif "Skin variants") + ## Helpful resources The [wiki](https://github.com/ether/etherpad-lite/wiki) is your one-stop resource for Tutorials and How-to's. @@ -97,6 +108,8 @@ Documentation can be found in `doc/`. ## Things you should know You can debug Etherpad using `bin/debugRun.sh`. +You can run Etherpad quickly launching `bin/fastRun.sh`. It's convenient for developers and advanced users. Be aware that it will skip the dependencies update, so remember to run `bin/installDeps.sh` after installing a new dependency or upgrading version. + If you want to find out how Etherpad's `Easysync` works (the library that makes it really realtime), start with this [PDF](https://github.com/ether/etherpad-lite/raw/master/doc/easysync/easysync-full-description.pdf) (complex, but worth reading). ## Contributing @@ -111,6 +124,8 @@ For **responsible disclosure of vulnerabilities**, please write a mail to the ma Etherpad is designed to be easily embeddable and provides a [HTTP API](https://github.com/ether/etherpad-lite/wiki/HTTP-API) that allows your web application to manage pads, users and groups. It is recommended to use the [available client implementations](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) in order to interact with this API. +OpenAPI (previously swagger) definitions for the API are exposed under `/api/openapi.json`. + # jQuery plugin There is a [jQuery plugin](https://github.com/ether/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website. diff --git a/bin/buildDebian.sh b/bin/buildDebian.sh index a0fa180a735..f1f5675ecfd 100755 --- a/bin/buildDebian.sh +++ b/bin/buildDebian.sh @@ -24,7 +24,7 @@ find ${SRC}/ -type d -exec chmod 0755 {} \; find ${SRC}/ -type f -exec chmod go-w {} \; chown -R root:root ${SRC}/ -let SIZE=`du -s ${SYSROOT} | sed s'/\s\+.*//'`+8 +let SIZE=$(du -s ${SYSROOT} | sed s'/\s\+.*//')+8 pushd ${SYSROOT}/ tar czf ${DIST}/data.tar.gz [a-z]* popd diff --git a/bin/buildForWindows.sh b/bin/buildForWindows.sh index 9d9e2f10d2d..3d6b61882f6 100755 --- a/bin/buildForWindows.sh +++ b/bin/buildForWindows.sh @@ -1,9 +1,9 @@ #!/bin/sh -NODE_VERSION="10.16.3" +NODE_VERSION="10.20.1" #Move to the folder where ep-lite is installed -cd `dirname $0` +cd $(dirname $0) #Was this script started in the bin folder? if yes move out if [ -d "../bin" ]; then diff --git a/bin/checkPadDeltas.js b/bin/checkPadDeltas.js new file mode 100644 index 00000000000..f1bd3ffe515 --- /dev/null +++ b/bin/checkPadDeltas.js @@ -0,0 +1,120 @@ +/* + * This is a debug tool. It checks all revisions for data corruption + */ + +if (process.argv.length != 3) { + console.error("Use: node bin/checkPadDeltas.js $PADID"); + process.exit(1); +} + +// get the padID +const padId = process.argv[2]; + +// load and initialize NPM; +var expect = require('expect.js') +var diff = require('diff') +var async = require('async') + +let npm = require('../src/node_modules/npm'); +var async = require("ep_etherpad-lite/node_modules/async"); +var Changeset = require("ep_etherpad-lite/static/js/Changeset"); + +npm.load({}, async function() { + + try { + // initialize database + let settings = require('../src/node/utils/Settings'); + let db = require('../src/node/db/DB'); + await db.init(); + + // load modules + let Changeset = require('ep_etherpad-lite/static/js/Changeset'); + let padManager = require('../src/node/db/PadManager'); + + let exists = await padManager.doesPadExists(padId); + if (!exists) { + console.error("Pad does not exist"); + process.exit(1); + } + + // get the pad + let pad = await padManager.getPad(padId); + + //create an array with key revisions + //key revisions always save the full pad atext + var head = pad.getHeadRevisionNumber(); + var keyRevisions = []; + for(var i=0;i require('marked').lexer('> i am using marked.') -[ { type: 'blockquote_start' }, - { type: 'text', text: ' i am using marked.' }, - { type: 'blockquote_end' }, - links: {} ] -``` - -## CLI - -``` bash -$ marked -o hello.html -hello world -^D -$ cat hello.html -

hello world

-``` - -## Syntax Highlighting - -Marked has an interface that allows for a syntax highlighter to highlight code -blocks before they're output. - -Example implementation: - -``` js -var highlight = require('my-syntax-highlighter') - , marked_ = require('marked'); - -var marked = function(text) { - var tokens = marked_.lexer(text) - , l = tokens.length - , i = 0 - , token; - - for (; i < l; i++) { - token = tokens[i]; - if (token.type === 'code') { - token.text = highlight(token.text, token.lang); - // marked should not escape this - token.escaped = true; - } - } - - text = marked_.parser(tokens); - - return text; -}; - -module.exports = marked; -``` - -## License - -Copyright (c) 2011-2012, Christopher Jeffrey. (MIT License) - -See LICENSE for more info. diff --git a/bin/doc/node_modules/marked/bin/marked b/bin/doc/node_modules/marked/bin/marked deleted file mode 100644 index 7d00504ed16..00000000000 --- a/bin/doc/node_modules/marked/bin/marked +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env node - -/** - * Marked CLI - * Copyright (c) 2011-2012, Christopher Jeffrey (MIT License) - */ - -var fs = require('fs') - , util = require('util') - , marked = require('../'); - -/** - * Man Page - */ - -var help = function() { - var spawn = require('child_process').spawn; - - var options = { - cwd: process.cwd(), - env: process.env, - setsid: false, - customFds: [0, 1, 2] - }; - - spawn('man', - [__dirname + '/../man/marked.1'], - options); -}; - -/** - * Main - */ - -var main = function(argv) { - var files = [] - , data = '' - , input - , output - , arg - , tokens; - - var getarg = function() { - var arg = argv.shift(); - arg = arg.split('='); - if (arg.length > 1) { - argv.unshift(arg.slice(1).join('=')); - } - return arg[0]; - }; - - while (argv.length) { - arg = getarg(); - switch (arg) { - case '-o': - case '--output': - output = argv.shift(); - break; - case '-i': - case '--input': - input = argv.shift(); - break; - case '-t': - case '--tokens': - tokens = true; - break; - case '-h': - case '--help': - return help(); - default: - files.push(arg); - break; - } - } - - if (!input) { - if (files.length <= 2) { - var stdin = process.stdin; - - stdin.setEncoding('utf8'); - stdin.resume(); - - stdin.on('data', function(text) { - data += text; - }); - - stdin.on('end', write); - - return; - } - input = files.pop(); - } - - data = fs.readFileSync(input, 'utf8'); - write(); - - function write() { - data = tokens - ? JSON.stringify(marked.lexer(data), null, 2) - : marked(data); - - if (!output) { - process.stdout.write(data + '\n'); - } else { - fs.writeFileSync(output, data); - } - } -}; - -if (!module.parent) { - process.title = 'marked'; - main(process.argv.slice()); -} else { - module.exports = main; -} diff --git a/bin/doc/node_modules/marked/index.js b/bin/doc/node_modules/marked/index.js deleted file mode 100644 index a12f90569fa..00000000000 --- a/bin/doc/node_modules/marked/index.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = require('./lib/marked'); diff --git a/bin/doc/node_modules/marked/lib/marked.js b/bin/doc/node_modules/marked/lib/marked.js deleted file mode 100644 index c6f3d0ac808..00000000000 --- a/bin/doc/node_modules/marked/lib/marked.js +++ /dev/null @@ -1,662 +0,0 @@ -/** - * marked - A markdown parser (https://github.com/chjj/marked) - * Copyright (c) 2011-2012, Christopher Jeffrey. (MIT Licensed) - */ - -;(function() { - -/** - * Block-Level Grammar - */ - -var block = { - newline: /^\n+/, - code: /^ {4,}[^\n]*(?:\n {4,}[^\n]*|\n)*(?:\n+|$)/, - gfm_code: /^ *``` *(\w+)? *\n([^\0]+?)\s*``` *(?:\n+|$)/, - hr: /^( *[\-*_]){3,} *(?:\n+|$)/, - heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/, - lheading: /^([^\n]+)\n *(=|-){3,} *\n*/, - blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/, - list: /^( *)([*+-]|\d+\.) [^\0]+?(?:\n{2,}(?! )|\s*$)(?!\1bullet)\n*/, - html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/, - def: /^ *\[([^\]]+)\]: *([^\s]+)(?: +["(]([^\n]+)[")])? *(?:\n+|$)/, - paragraph: /^([^\n]+\n?(?!body))+\n*/, - text: /^[^\n]+/ -}; - -block.list = (function() { - var list = block.list.source; - - list = list - .replace('bullet', /(?:[*+-](?!(?: *[-*]){2,})|\d+\.)/.source); - - return new RegExp(list); -})(); - -block.html = (function() { - var html = block.html.source; - - html = html - .replace('comment', //.source) - .replace('closed', /<(tag)[^\0]+?<\/\1>/.source) - .replace('closing', /])*?>/.source) - .replace(/tag/g, tag()); - - return new RegExp(html); -})(); - -block.paragraph = (function() { - var paragraph = block.paragraph.source - , body = []; - - (function push(rule) { - rule = block[rule] ? block[rule].source : rule; - body.push(rule.replace(/(^|[^\[])\^/g, '$1')); - return push; - }) - ('gfm_code') - ('hr') - ('heading') - ('lheading') - ('blockquote') - ('<' + tag()) - ('def'); - - return new - RegExp(paragraph.replace('body', body.join('|'))); -})(); - -/** - * Block Lexer - */ - -block.lexer = function(src) { - var tokens = []; - - tokens.links = {}; - - src = src - .replace(/\r\n|\r/g, '\n') - .replace(/\t/g, ' '); - - return block.token(src, tokens, true); -}; - -block.token = function(src, tokens, top) { - var src = src.replace(/^ +$/gm, '') - , next - , loose - , cap - , item - , space - , i - , l; - - while (src) { - // newline - if (cap = block.newline.exec(src)) { - src = src.substring(cap[0].length); - if (cap[0].length > 1) { - tokens.push({ - type: 'space' - }); - } - } - - // code - if (cap = block.code.exec(src)) { - src = src.substring(cap[0].length); - cap = cap[0].replace(/^ {4}/gm, ''); - tokens.push({ - type: 'code', - text: cap.replace(/\n+$/, '') - }); - continue; - } - - // gfm_code - if (cap = block.gfm_code.exec(src)) { - src = src.substring(cap[0].length); - tokens.push({ - type: 'code', - lang: cap[1], - text: cap[2] - }); - continue; - } - - // heading - if (cap = block.heading.exec(src)) { - src = src.substring(cap[0].length); - tokens.push({ - type: 'heading', - depth: cap[1].length, - text: cap[2] - }); - continue; - } - - // lheading - if (cap = block.lheading.exec(src)) { - src = src.substring(cap[0].length); - tokens.push({ - type: 'heading', - depth: cap[2] === '=' ? 1 : 2, - text: cap[1] - }); - continue; - } - - // hr - if (cap = block.hr.exec(src)) { - src = src.substring(cap[0].length); - tokens.push({ - type: 'hr' - }); - continue; - } - - // blockquote - if (cap = block.blockquote.exec(src)) { - src = src.substring(cap[0].length); - tokens.push({ - type: 'blockquote_start' - }); - - cap = cap[0].replace(/^ *> ?/gm, ''); - - // Pass `top` to keep the current - // "toplevel" state. This is exactly - // how markdown.pl works. - block.token(cap, tokens, top); - - tokens.push({ - type: 'blockquote_end' - }); - continue; - } - - // list - if (cap = block.list.exec(src)) { - src = src.substring(cap[0].length); - - tokens.push({ - type: 'list_start', - ordered: isFinite(cap[2]) - }); - - // Get each top-level item. - cap = cap[0].match( - /^( *)([*+-]|\d+\.)[^\n]*(?:\n(?!\1(?:[*+-]|\d+\.))[^\n]*)*/gm - ); - - next = false; - l = cap.length; - i = 0; - - for (; i < l; i++) { - item = cap[i]; - - // Remove the list item's bullet - // so it is seen as the next token. - space = item.length; - item = item.replace(/^ *([*+-]|\d+\.) */, ''); - - // Outdent whatever the - // list item contains. Hacky. - if (~item.indexOf('\n ')) { - space -= item.length; - item = item.replace(new RegExp('^ {1,' + space + '}', 'gm'), ''); - } - - // Determine whether item is loose or not. - // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/ - // for discount behavior. - loose = next || /\n\n(?!\s*$)/.test(item); - if (i !== l - 1) { - next = item[item.length-1] === '\n'; - if (!loose) loose = next; - } - - tokens.push({ - type: loose - ? 'loose_item_start' - : 'list_item_start' - }); - - // Recurse. - block.token(item, tokens); - - tokens.push({ - type: 'list_item_end' - }); - } - - tokens.push({ - type: 'list_end' - }); - - continue; - } - - // html - if (cap = block.html.exec(src)) { - src = src.substring(cap[0].length); - tokens.push({ - type: 'html', - text: cap[0] - }); - continue; - } - - // def - if (top && (cap = block.def.exec(src))) { - src = src.substring(cap[0].length); - tokens.links[cap[1].toLowerCase()] = { - href: cap[2], - title: cap[3] - }; - continue; - } - - // top-level paragraph - if (top && (cap = block.paragraph.exec(src))) { - src = src.substring(cap[0].length); - tokens.push({ - type: 'paragraph', - text: cap[0] - }); - continue; - } - - // text - if (cap = block.text.exec(src)) { - // Top-level should never reach here. - src = src.substring(cap[0].length); - tokens.push({ - type: 'text', - text: cap[0] - }); - continue; - } - } - - return tokens; -}; - -/** - * Inline Processing - */ - -var inline = { - escape: /^\\([\\`*{}\[\]()#+\-.!_>])/, - autolink: /^<([^ >]+(@|:\/)[^ >]+)>/, - gfm_autolink: /^(\w+:\/\/[^\s]+[^.,:;"')\]\s])/, - tag: /^|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/, - link: /^!?\[((?:\[[^\]]*\]|[^\[\]]|\[|\](?=[^[\]]*\]))*)\]\(([^\)]*)\)/, - reflink: /^!?\[((?:\[[^\]]*\]|[^\[\]]|\[|\](?=[^[\]]*\]))*)\]\s*\[([^\]]*)\]/, - nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/, - strong: /^__([^\0]+?)__(?!_)|^\*\*([^\0]+?)\*\*(?!\*)/, - em: /^\b_([^\0]+?)_\b|^\*((?:\*\*|[^\0])+?)\*(?!\*)/, - code: /^(`+)([^\0]*?[^`])\1(?!`)/, - br: /^ {2,}\n(?!\s*$)/, - text: /^[^\0]+?(?=[\\' - + text - + ''; - continue; - } - - // gfm_autolink - if (cap = inline.gfm_autolink.exec(src)) { - src = src.substring(cap[0].length); - text = escape(cap[1]); - href = text; - out += '' - + text - + ''; - continue; - } - - // tag - if (cap = inline.tag.exec(src)) { - src = src.substring(cap[0].length); - out += cap[0]; - continue; - } - - // link - if (cap = inline.link.exec(src)) { - src = src.substring(cap[0].length); - text = /^\s*?(?:\s+"([^\n]+)")?\s*$/.exec(cap[2]); - if (!text) { - out += cap[0][0]; - src = cap[0].substring(1) + src; - continue; - } - out += outputLink(cap, { - href: text[1], - title: text[2] - }); - continue; - } - - // reflink, nolink - if ((cap = inline.reflink.exec(src)) - || (cap = inline.nolink.exec(src))) { - src = src.substring(cap[0].length); - link = (cap[2] || cap[1]).replace(/\s+/g, ' '); - link = links[link.toLowerCase()]; - if (!link || !link.href) { - out += cap[0][0]; - src = cap[0].substring(1) + src; - continue; - } - out += outputLink(cap, link); - continue; - } - - // strong - if (cap = inline.strong.exec(src)) { - src = src.substring(cap[0].length); - out += '' - + inline.lexer(cap[2] || cap[1]) - + ''; - continue; - } - - // em - if (cap = inline.em.exec(src)) { - src = src.substring(cap[0].length); - out += '' - + inline.lexer(cap[2] || cap[1]) - + ''; - continue; - } - - // code - if (cap = inline.code.exec(src)) { - src = src.substring(cap[0].length); - out += '' - + escape(cap[2], true) - + ''; - continue; - } - - // br - if (cap = inline.br.exec(src)) { - src = src.substring(cap[0].length); - out += '
'; - continue; - } - - // text - if (cap = inline.text.exec(src)) { - src = src.substring(cap[0].length); - out += escape(cap[0]); - continue; - } - } - - return out; -}; - -var outputLink = function(cap, link) { - if (cap[0][0] !== '!') { - return '' - + inline.lexer(cap[1]) - + ''; - } else { - return ''
-      + escape(cap[1])
-      + ''; - } -}; - -/** - * Parsing - */ - -var tokens - , token; - -var next = function() { - return token = tokens.pop(); -}; - -var tok = function() { - switch (token.type) { - case 'space': { - return ''; - } - case 'hr': { - return '
\n'; - } - case 'heading': { - return '' - + inline.lexer(token.text) - + '\n'; - } - case 'code': { - return '
'
-        + (token.escaped
-        ? token.text
-        : escape(token.text, true))
-        + '
\n'; - } - case 'blockquote_start': { - var body = ''; - - while (next().type !== 'blockquote_end') { - body += tok(); - } - - return '
\n' - + body - + '
\n'; - } - case 'list_start': { - var type = token.ordered ? 'ol' : 'ul' - , body = ''; - - while (next().type !== 'list_end') { - body += tok(); - } - - return '<' - + type - + '>\n' - + body - + '\n'; - } - case 'list_item_start': { - var body = ''; - - while (next().type !== 'list_item_end') { - body += token.type === 'text' - ? parseText() - : tok(); - } - - return '
  • ' - + body - + '
  • \n'; - } - case 'loose_item_start': { - var body = ''; - - while (next().type !== 'list_item_end') { - body += tok(); - } - - return '
  • ' - + body - + '
  • \n'; - } - case 'html': { - return inline.lexer(token.text); - } - case 'paragraph': { - return '

    ' - + inline.lexer(token.text) - + '

    \n'; - } - case 'text': { - return '

    ' - + parseText() - + '

    \n'; - } - } -}; - -var parseText = function() { - var body = token.text - , top; - - while ((top = tokens[tokens.length-1]) - && top.type === 'text') { - body += '\n' + next().text; - } - - return inline.lexer(body); -}; - -var parse = function(src) { - tokens = src.reverse(); - - var out = ''; - while (next()) { - out += tok(); - } - - tokens = null; - token = null; - - return out; -}; - -/** - * Helpers - */ - -var escape = function(html, encode) { - return html - .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); -}; - -var mangle = function(text) { - var out = '' - , l = text.length - , i = 0 - , ch; - - for (; i < l; i++) { - ch = text.charCodeAt(i); - if (Math.random() > 0.5) { - ch = 'x' + ch.toString(16); - } - out += '&#' + ch + ';'; - } - - return out; -}; - -function tag() { - var tag = '(?!(?:' - + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code' - + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo' - + '|span|br|wbr|ins|del|img)\\b)\\w+'; - - return tag; -} - -/** - * Expose - */ - -var marked = function(src) { - return parse(block.lexer(src)); -}; - -marked.parser = parse; -marked.lexer = block.lexer; - -marked.parse = marked; - -if (typeof module !== 'undefined') { - module.exports = marked; -} else { - this.marked = marked; -} - -}).call(this); diff --git a/bin/doc/node_modules/marked/man/marked.1 b/bin/doc/node_modules/marked/man/marked.1 deleted file mode 100644 index 214533390ce..00000000000 --- a/bin/doc/node_modules/marked/man/marked.1 +++ /dev/null @@ -1,39 +0,0 @@ -.ds q \N'34' -.TH marked 1 -.SH NAME -marked \- a javascript markdown parser -.SH SYNOPSIS -.nf -.B marked [\-o output] [\-i input] [\-th] -.fi -.SH DESCRIPTION -.B marked -is a full-featured javascript markdown parser, built for speed. It also includes -multiple GFM features. -.SH OPTIONS -.TP -.BI \-o,\ \-\-output\ [output] -Specify file output. If none is specified, write to stdout. -.TP -.BI \-i,\ \-\-input\ [input] -Specify file input, otherwise use last argument as input file. If no input file -is specified, read from stdin. -.TP -.BI \-t,\ \-\-tokens -Output a token stream instead of html. -.TP -.BI \-h,\ \-\-help -Display help information. -.SH EXAMPLES -.TP -cat in.md | marked > out.html -.TP -echo "hello *world*" | marked -.TP -marked -o out.html in.md -.TP -marked --output="hello world.html" -i in.md -.SH BUGS -Please report any bugs to https://github.com/chjj/marked. -.SH LICENSE -Copyright (c) 2011-2012, Christopher Jeffrey (MIT License) diff --git a/bin/doc/node_modules/marked/package.json b/bin/doc/node_modules/marked/package.json deleted file mode 100644 index f47a9e12530..00000000000 --- a/bin/doc/node_modules/marked/package.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "name": "marked", - "description": "A markdown parser built for speed", - "author": "Christopher Jeffrey", - "version": "0.1.9", - "main": "./lib/marked.js", - "bin": "./bin/marked", - "man": "./man/marked.1", - "preferGlobal": false, - "repository": "git://github.com/chjj/marked.git", - "homepage": "https://github.com/chjj/marked", - "bugs": "http://github.com/chjj/marked/issues", - "keywords": [ "markdown", "markup", "html" ], - "tags": [ "markdown", "markup", "html" ] -} diff --git a/bin/doc/package-lock.json b/bin/doc/package-lock.json new file mode 100644 index 00000000000..eb552613570 --- /dev/null +++ b/bin/doc/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "node-doc-generator", + "version": "0.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "marked": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.2.tgz", + "integrity": "sha512-EGwzEeCcLniFX51DhTpmTom+dSA/MG/OBUDjnWtHbEnjAH180VzUeAw+oE4+Zv+CoYBWyRlYOTR0N8SO9R1PVw==" + } + } +} diff --git a/bin/doc/package.json b/bin/doc/package.json index 5aba79e05d3..1a29f1b1c79 100644 --- a/bin/doc/package.json +++ b/bin/doc/package.json @@ -7,7 +7,7 @@ "node": ">=0.6.10" }, "dependencies": { - "marked": ">=0.3.6" + "marked": "0.8.2" }, "devDependencies": {}, "optionalDependencies": {}, diff --git a/bin/fastRun.sh b/bin/fastRun.sh new file mode 100755 index 00000000000..e00bb8c72c4 --- /dev/null +++ b/bin/fastRun.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# +# Run Etherpad directly, assuming all the dependencies are already installed. +# +# Useful for developers, or users that know what they are doing. If you just +# upgraded Etherpad version, installed a new dependency, or are simply unsure +# of what to do, please execute bin/installDeps.sh once before running this +# script. + +set -eu + +# source: https://stackoverflow.com/questions/59895/how-to-get-the-source-directory-of-a-bash-script-from-within-the-script-itself#246128 +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + +echo "Running directly, without checking/installing dependencies" + +# move to the base Etherpad directory. This will be necessary until Etherpad +# learns to run from arbitrary CWDs. +cd "${DIR}/.." + +# run Etherpad main class +node "${DIR}/../node_modules/ep_etherpad-lite/node/server.js" "${@}" diff --git a/bin/installDeps.sh b/bin/installDeps.sh index 49c996f46c4..50310d9a1e1 100755 --- a/bin/installDeps.sh +++ b/bin/installDeps.sh @@ -1,8 +1,8 @@ #!/bin/sh # minimum required node version -REQUIRED_NODE_MAJOR=8 -REQUIRED_NODE_MINOR=9 +REQUIRED_NODE_MAJOR=10 +REQUIRED_NODE_MINOR=13 # minimum required npm version REQUIRED_NPM_MAJOR=5 @@ -49,7 +49,7 @@ require_minimal_version() { } #Move to the folder where ep-lite is installed -cd `dirname $0` +cd $(dirname $0) #Was this script started in the bin folder? if yes move out if [ -d "../bin" ]; then diff --git a/bin/run.sh b/bin/run.sh index e9ea6244021..74fa56d683e 100755 --- a/bin/run.sh +++ b/bin/run.sh @@ -1,7 +1,7 @@ #!/bin/sh #Move to the folder where ep-lite is installed -cd `dirname $0` +cd $(dirname $0) #Was this script started in the bin folder? if yes move out if [ -d "../bin" ]; then @@ -34,6 +34,6 @@ bin/installDeps.sh "$@" || exit 1 #Move to the node folder and start echo "Started Etherpad..." -SCRIPTPATH=`pwd -P` +SCRIPTPATH=$(pwd -P) exec node "$SCRIPTPATH/node_modules/ep_etherpad-lite/node/server.js" "$@" diff --git a/bin/safeRun.sh b/bin/safeRun.sh index 484c325eaf4..99a72bcc03c 100755 --- a/bin/safeRun.sh +++ b/bin/safeRun.sh @@ -19,7 +19,7 @@ LAST_EMAIL_SEND=0 LOG="$1" #Move to the folder where ep-lite is installed -cd `dirname $0` +cd $(dirname $0) #Was this script started in the bin folder? if yes move out if [ -d "../bin" ]; then diff --git a/bin/updatePlugins.sh b/bin/updatePlugins.sh index 63c447edf3f..ce7a46f6bbd 100755 --- a/bin/updatePlugins.sh +++ b/bin/updatePlugins.sh @@ -1,7 +1,7 @@ #!/bin/sh #Move to the folder where ep-lite is installed -cd `dirname $0` +cd $(dirname $0) #Was this script started in the bin folder? if yes move out if [ -d "../bin" ]; then @@ -9,7 +9,7 @@ if [ -d "../bin" ]; then fi # npm outdated --depth=0 | grep -v "^Package" | awk '{print $1}' | xargs npm install $1 --save-dev -OUTDATED=`npm outdated --depth=0 | grep -v "^Package" | awk '{print $1}'` +OUTDATED=$(npm outdated --depth=0 | grep -v "^Package" | awk '{print $1}') # echo $OUTDATED if test -n "$OUTDATED"; then echo "Plugins require update, doing this now..." diff --git a/doc/api/hooks_client-side.md b/doc/api/hooks_client-side.md old mode 100644 new mode 100755 index f30578d7e31..799fd5ce5cb --- a/doc/api/hooks_client-side.md +++ b/doc/api/hooks_client-side.md @@ -193,6 +193,16 @@ Called from: src/static/js/timeslider.js There doesn't appear to be any example available of this particular hook being used, but it gets fired after the timeslider is all set up. +## goToRevisionEvent +Called from: src/static/js/broadcast.js + +Things in context: + +1. rev - The newRevision + +This hook gets fired both on timeslider load (as timeslider shows a new revision) and when the new revision is showed to a user. +There doesn't appear to be any example available of this particular hook being used. + ## userJoinOrUpdate Called from: src/static/js/pad_userlist.js @@ -209,10 +219,11 @@ Things in context: 1. authorName - The user that wrote this message 2. author - The authorID of the user that wrote the message -2. text - the message text -3. sticky (boolean) - if you want the gritter notification bubble to fade out on its own or just sit there -3. timestamp - the timestamp of the chat message -4. timeStr - the timestamp as a formatted string +3. text - the message text +4. sticky (boolean) - if you want the gritter notification bubble to fade out on its own or just sit there +5. timestamp - the timestamp of the chat message +6. timeStr - the timestamp as a formatted string +7. duration - for how long in milliseconds should the gritter notification appear (0 to disable) This hook is called on the client side whenever a chat message is received from the server. It can be used to create different notifications for chat messages. diff --git a/doc/api/http_api.md b/doc/api/http_api.md index 2105e4fde22..5be9cb3a411 100644 --- a/doc/api/http_api.md +++ b/doc/api/http_api.md @@ -11,6 +11,10 @@ The API is designed in a way, so you can reuse your existing user system with th Take a look at [HTTP API client libraries](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) to check if a library in your favorite programming language is available. +### OpenAPI + +OpenAPI (formerly swagger) definitions are exposed under `/api/openapi.json` (latest) and `/api/{version}/openapi.json`. You can use official tools like [Swagger Editor](https://editor.swagger.io/) to view and explore them. + ## Examples ### Example 1 @@ -61,7 +65,7 @@ Portal submits content into new blog post ## Usage ### API version -The latest version is `1.2.13` +The latest version is `1.2.14` The current version can be queried via /api. @@ -630,3 +634,14 @@ lists all pads on this epl instance *Example returns:* * `{code: 0, message:"ok", data: {padIDs: ["testPad", "thePadsOfTheOthers"]}}` + +### Global + +#### getStats() + * API >= 1.2.14 + +get stats of the etherpad instance + +*Example returns* + * `{"code":0,"message":"ok","data":{"totalPads":3,"totalSessions": 2,"totalActivePads": 1}}` + diff --git a/doc/cookies.md b/doc/cookies.md new file mode 100644 index 00000000000..54184959652 --- /dev/null +++ b/doc/cookies.md @@ -0,0 +1,18 @@ +# Cookies + +Cookies used by Etherpad. + +| Name | Sample value | Domain | Path | Expires/max-age | Http-only| Secure | Usage description | +|-----------------|------------------------------------|-------------|------|-----------------|----------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +|express_sid | s%3A7yCNjRmTW8ylGQ53I2IhOwYF9... | example.org | / | Session | true | true | Session ID of the [Express web framework](https://expressjs.com). When Etherpad is behind a reverse proxy, and an administrator wants to use session stickiness, he may use this cookie. If you are behind a reverse proxy, please remember to set `trustProxy: true` in `settings.json`. Set in [webaccess.js#L131](https://github.com/ether/etherpad-lite/blob/01497aa399690e44393e91c19917d11d025df71b/src/node/hooks/express/webaccess.js#L131). | +|language | en | example.org | / | Session | false | true | The language of the UI (e.g.: `en-GB`, `it`). Set in [pad_editor.js#L111](https://github.com/ether/etherpad-lite/blob/01497aa399690e44393e91c19917d11d025df71b/src/static/js/pad_editor.js#L111). | +|prefs / prefsHttp| %7B%22epThemesExtTheme%22... | example.org | /p | year 3000 | false | true | Client-side preferences (e.g.: font family, chat always visible, show authorship colors, ...). Set in [pad_cookie.js#L49](https://github.com/ether/etherpad-lite/blob/01497aa399690e44393e91c19917d11d025df71b/src/static/js/pad_cookie.js#L49). `prefs` is used if Etherpad is accessed over HTTPS, `prefsHttp` if accessed over HTTP. For more info see https://github.com/ether/etherpad-lite/issues/3179. | +|token | t.tFzkihhhBf4xKEpCK3PU | example.org | / | 60 days | false | true | A random token representing the author, of the form `t.randomstring_of_lenght_20`. The random string is generated by the client, at ([pad.js#L55-L66](https://github.com/ether/etherpad-lite/blob/01497aa399690e44393e91c19917d11d025df71b/src/static/js/pad.js#L55-L66)). This cookie is always set by the client (at [pad.js#L153-L158](https://github.com/ether/etherpad-lite/blob/01497aa399690e44393e91c19917d11d025df71b/src/static/js/pad.js#L153-L158)) without any solicitation from the server. It is used for all the pads accessed via the web UI (not used for the HTTP API). On the server side, its value is accessed at [SecurityManager.js#L33](https://github.com/ether/etherpad-lite/blob/01497aa399690e44393e91c19917d11d025df71b/src/node/db/SecurityManager.js#L33).| + +For more info, visit the related discussion at https://github.com/ether/etherpad-lite/issues/3563. + +Etherpad HTTP API clients may make use (if they choose so) to send another cookie: + +| Name | Sample value | Domain | Usage description | +|-----------------|------------------------------------|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +|sessionID | s.1c70968b333b25476a2c7bdd0e0bed17 | example.org | Sessions can be created between a group and an author. This allows an author to access more than one group. The sessionID will be set as a cookie to the client and is valid until a certain date. The session cookie can also contain multiple comma-separated sessionIDs, allowing a user to edit pads in different groups at the same time. More info - https://github.com/ether/etherpad-lite/blob/develop/doc/api/http_api.md#session | diff --git a/doc/docker.md b/doc/docker.md index e77cde4093e..9a991a602ee 100644 --- a/doc/docker.md +++ b/doc/docker.md @@ -16,6 +16,7 @@ docker pull etherpad/etherpad:1.8.0 If you want to use a personalized settings file, **you will have to rebuild your image**. All of the following instructions are as a member of the `docker` group. +By default, the Etherpad Docker image is built and run in `production` mode: no development dependencies are installed, and asset bundling speeds up page load time. ### Rebuilding with custom settings Edit `/settings.json.docker` at your will. When rebuilding the image, this file will be copied inside your image and renamed to `setting.json`. @@ -51,28 +52,143 @@ And point your browser to `http://:` ## Options available by default -The `settings.json.docker` available by default enables some configuration to be set from the environment. - -Available options: - -* `TITLE`: The name of the instance -* `FAVICON`: favicon default name, or a fully specified URL to your own favicon -* `SKIN_NAME`: either `no-skin`, `colibris` or an existing directory under `src/static/skins`. -* `IP`: IP which etherpad should bind at. Change to `::` for IPv6 -* `PORT`: port which etherpad should bind at -* `SHOW_SETTINGS_IN_ADMIN_PAGE`: hide/show the settings.json in admin page -* `DB_TYPE`: a database supported by https://www.npmjs.com/package/ueberdb2 -* `DB_HOST`: the host of the database -* `DB_PORT`: the port of the database -* `DB_NAME`: the database name -* `DB_USER`: a database user with sufficient permissions to create tables -* `DB_PASS`: the password for the database username -* `DB_CHARSET`: the character set for the tables (only required for MySQL) -* `DB_FILENAME`: in case `DB_TYPE` is `DirtyDB`, the database filename. Default: `var/dirty.db` -* `ADMIN_PASSWORD`: the password for the `admin` user (leave unspecified if you do not want to create it) -* `USER_PASSWORD`: the password for the first user `user` (leave unspecified if you do not want to create it) -* `TRUST_PROXY`: set to `true` if you are using a reverse proxy in front of Etherpad (for example: Traefik for SSL termination via Let's Encrypt). This will affect security and correctness of the logs if not done -* `LOGLEVEL`: valid values are `DEBUG`, `INFO`, `WARN` and `ERROR` +The `settings.json.docker` available by default allows to control almost every setting via environment variables. + +### General + +| Variable | Description | Default | +| ------------------ | ------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `TITLE` | The name of the instance | `Etherpad` | +| `FAVICON` | favicon default name, or a fully specified URL to your own favicon | `favicon.ico` | +| `DEFAULT_PAD_TEXT` | The default text of a pad | `Welcome to Etherpad! This pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents! Get involved with Etherpad at https://etherpad.org` | +| `IP` | IP which etherpad should bind at. Change to `::` for IPv6 | `0.0.0.0` | +| `PORT` | port which etherpad should bind at | `9001` | +| `ADMIN_PASSWORD` | the password for the `admin` user (leave unspecified if you do not want to create it) | | +| `USER_PASSWORD` | the password for the first user `user` (leave unspecified if you do not want to create it) | | + + +### Database + +| Variable | Description | Default | +| ------------- | -------------------------------------------------------------- | --------------------------------------------------------------------- | +| `DB_TYPE` | a database supported by https://www.npmjs.com/package/ueberdb2 | not set, thus will fall back to `DirtyDB` (please choose one instead) | +| `DB_HOST` | the host of the database | | +| `DB_PORT` | the port of the database | | +| `DB_NAME` | the database name | | +| `DB_USER` | a database user with sufficient permissions to create tables | | +| `DB_PASS` | the password for the database username | | +| `DB_CHARSET` | the character set for the tables (only required for MySQL) | | +| `DB_FILENAME` | in case `DB_TYPE` is `DirtyDB`, the database filename. | `var/dirty.db` | + +If your database needs additional settings, you will have to use a personalized `settings.json.docker` and rebuild the container (or otherwise put the updated `settings.json` inside your image). + + +### Pad Options + +| Variable | Description | Default | +| -------------------------------- | ----------- | ------- | +| `PAD_OPTIONS_NO_COLORS` | | `false` | +| `PAD_OPTIONS_SHOW_CONTROLS` | | `true` | +| `PAD_OPTIONS_SHOW_CHAT` | | `true` | +| `PAD_OPTIONS_SHOW_LINE_NUMBERS` | | `true` | +| `PAD_OPTIONS_USE_MONOSPACE_FONT` | | `false` | +| `PAD_OPTIONS_USER_NAME` | | `false` | +| `PAD_OPTIONS_USER_COLOR` | | `false` | +| `PAD_OPTIONS_RTL` | | `false` | +| `PAD_OPTIONS_ALWAYS_SHOW_CHAT` | | `false` | +| `PAD_OPTIONS_CHAT_AND_USERS` | | `false` | +| `PAD_OPTIONS_LANG` | | `en-gb` | + + +### Shortcuts + +| Variable | Description | Default | +| ----------------------------------- | ------------------------------------------------ | ------- | +| `PAD_SHORTCUTS_ENABLED_ALT_F9` | focus on the File Menu and/or editbar | `true` | +| `PAD_SHORTCUTS_ENABLED_ALT_C` | focus on the Chat window | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_S` | save a revision | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_Z` | undo/redo | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_Y` | redo | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_I` | italic | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_B` | bold | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_U` | underline | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_H` | backspace | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_5` | strike through | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_SHIFT_1` | ordered list | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_SHIFT_2` | shows a gritter popup showing a line author | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_SHIFT_L` | unordered list | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_SHIFT_N` | ordered list | `true` | +| `PAD_SHORTCUTS_ENABLED_CMD_SHIFT_C` | clear authorship | `true` | +| `PAD_SHORTCUTS_ENABLED_DELETE` | | `true` | +| `PAD_SHORTCUTS_ENABLED_RETURN` | | `true` | +| `PAD_SHORTCUTS_ENABLED_ESC` | in mozilla versions 14-19 avoid reconnecting pad | `true` | +| `PAD_SHORTCUTS_ENABLED_TAB` | indent | `true` | +| `PAD_SHORTCUTS_ENABLED_CTRL_HOME` | scroll to top of pad | `true` | +| `PAD_SHORTCUTS_ENABLED_PAGE_UP` | | `true` | +| `PAD_SHORTCUTS_ENABLED_PAGE_DOWN` | | `true` | + + +### Skins + +You can use the UI skin variants builder at `/p/test#skinvariantsbuilder` + +For the colibris skin only, you can choose how to render the three main containers: + * toolbar (top menu with icons) + * editor (containing the text of the pad) + * background (area outside of editor, mostly visible when using page style) + +For each of the 3 containers you can choose 4 color combinations: + * super-light + * light + * dark + * super-dark + +For the editor container, you can also make it full width by adding `full-width-editor` variant (by default editor is rendered as a page, with a max-width of 900px). + +| Variable | Description | Default | +| --------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------- | +| `SKIN_NAME` | either `no-skin`, `colibris` or an existing directory under `src/static/skins` | `colibris` | +| `SKIN_VARIANTS` | multiple skin variants separated by spaces | `super-light-toolbar super-light-editor light-background` | + + +### Logging + +| Variable | Description | Default | +| -------------------- | ---------------------------------------------------- | ------- | +| `LOGLEVEL` | valid values are `DEBUG`, `INFO`, `WARN` and `ERROR` | `INFO` | +| `DISABLE_IP_LOGGING` | Privacy: disable IP logging | `false` | + + +### Advanced + +| Variable | Description | Default | +| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------ | +| `SHOW_SETTINGS_IN_ADMIN_PAGE` | hide/show the settings.json in admin page | `true` | +| `TRUST_PROXY` | set to `true` if you are using a reverse proxy in front of Etherpad (for example: Traefik for SSL termination via Let's Encrypt). This will affect security and correctness of the logs if not done | `false` | +| `IMPORT_MAX_FILE_SIZE` | maximum allowed file size when importing a pad, in bytes. | `52428800` (50 MB) | +| `IMPORT_EXPORT_MAX_REQ_PER_IP` | maximum number of import/export calls per IP. | `10` | +| `IMPORT_EXPORT_RATE_LIMIT_WINDOW` | the call rate for import/export requests will be estimated in this time window (in milliseconds) | `90000` | +| `SUPPRESS_ERRORS_IN_PAD_TEXT` | Should we suppress errors from being visible in the default Pad Text? | `false` | +| `REQUIRE_SESSION` | If this option is enabled, a user must have a session to access pads. This effectively allows only group pads to be accessed. | `false` | +| `EDIT_ONLY` | Users may edit pads but not create new ones. Pad creation is only via the API. This applies both to group pads and regular pads. | `false` | +| `SESSION_NO_PASSWORD` | If set to true, those users who have a valid session will automatically be granted access to password protected pads. | `false` | +| `MINIFY` | If true, all css & js will be minified before sending to the client. This will improve the loading performance massively, but makes it difficult to debug the javascript/css | `true` | +| `MAX_AGE` | How long may clients use served javascript code (in seconds)? Not setting this may cause problems during deployment. Set to 0 to disable caching. | `21600` (6 hours) | +| `ABIWORD` | Absolute path to the Abiword executable. Abiword is needed to get advanced import/export features of pads. Setting it to null disables Abiword and will only allow plain text and HTML import/exports. | `null` | +| `SOFFICE` | This is the absolute path to the soffice executable. LibreOffice can be used in lieu of Abiword to export pads. Setting it to null disables LibreOffice exporting. | `null` | +| `TIDY_HTML` | Path to the Tidy executable. Tidy is used to improve the quality of exported pads. Setting it to null disables Tidy. | `null` | +| `ALLOW_UNKNOWN_FILE_ENDS` | Allow import of file types other than the supported ones: txt, doc, docx, rtf, odt, html & htm | `true` | +| `REQUIRE_AUTHENTICATION` | This setting is used if you require authentication of all users. Note: "/admin" always requires authentication. | `false` | +| `REQUIRE_AUTHORIZATION` | Require authorization by a module, or a user with is_admin set, see below. | `false` | +| `AUTOMATIC_RECONNECTION_TIMEOUT` | Time (in seconds) to automatically reconnect pad when a "Force reconnect" message is shown to user. Set to 0 to disable automatic reconnection. | `0` | +| `FOCUS_LINE_PERCENTAGE_ABOVE` | Percentage of viewport height to be additionally scrolled. e.g. 0.5, to place caret line in the middle of viewport, when user edits a line above of the viewport. Set to 0 to disable extra scrolling | `0` | +| `FOCUS_LINE_PERCENTAGE_BELOW` | Percentage of viewport height to be additionally scrolled. e.g. 0.5, to place caret line in the middle of viewport, when user edits a line below of the viewport. Set to 0 to disable extra scrolling | `0` | +| `FOCUS_LINE_PERCENTAGE_ARROW_UP` | Percentage of viewport height to be additionally scrolled when user presses arrow up in the line of the top of the viewport. Set to 0 to let the scroll to be handled as default by Etherpad | `0` | +| `FOCUS_LINE_DURATION` | Time (in milliseconds) used to animate the scroll transition. Set to 0 to disable animation | `0` | +| `FOCUS_LINE_CARET_SCROLL` | Flag to control if it should scroll when user places the caret in the last line of the viewport | `false` | +| `LOAD_TEST` | Allow Load Testing tools to hit the Etherpad Instance. WARNING: this will disable security on the instance. | `false` | +| `EXPOSE_VERSION` | Expose Etherpad version in the web interface and in the Server http header. Do not enable on production machines. | `false` | + ### Examples @@ -100,3 +216,12 @@ docker run -d \ -e 'ADMIN_PASSWORD=supersecret' \ etherpad/etherpad ``` + +Run a test instance running DirtyDB on a persistent volume: + +``` +docker run -d \ + -v etherpad_data:/opt/etherpad-lite/var \ + -p 9001:9001 \ + etherpad/etherpad +``` diff --git a/doc/images/etherpad_basic.png b/doc/images/etherpad_basic.png new file mode 100644 index 00000000000..1b5d32ef5ae Binary files /dev/null and b/doc/images/etherpad_basic.png differ diff --git a/doc/images/etherpad_demo.gif b/doc/images/etherpad_demo.gif new file mode 100644 index 00000000000..2fa8464f7cf Binary files /dev/null and b/doc/images/etherpad_demo.gif differ diff --git a/doc/images/etherpad_full_features.png b/doc/images/etherpad_full_features.png new file mode 100644 index 00000000000..4b0d5f0ced8 Binary files /dev/null and b/doc/images/etherpad_full_features.png differ diff --git a/doc/images/etherpad_skin_variants.gif b/doc/images/etherpad_skin_variants.gif new file mode 100644 index 00000000000..09056979fdb Binary files /dev/null and b/doc/images/etherpad_skin_variants.gif differ diff --git a/doc/index.md b/doc/index.md index 4f03bbef428..06bed80e1b1 100644 --- a/doc/index.md +++ b/doc/index.md @@ -5,4 +5,5 @@ @include skins @include api/api @include plugins +@include cookies @include database diff --git a/doc/plugins.md b/doc/plugins.md index a91569ad57d..513e3857708 100644 --- a/doc/plugins.md +++ b/doc/plugins.md @@ -115,7 +115,7 @@ Your plugin must also contain a [package definition file](https://docs.npmjs.com "author": "USERNAME (REAL NAME) ", "contributors": [], "dependencies": {"MODULE": "0.3.20"}, - "engines": { "node": ">= 8.9.0"} + "engines": { "node": ">= 10.13.0"} } ``` diff --git a/settings.json.docker b/settings.json.docker index ef989325842..2f2d0092ed7 100644 --- a/settings.json.docker +++ b/settings.json.docker @@ -65,6 +65,13 @@ * "password": "${PASSW}" // if PASSW is not defined would result in password === null * "password": "${PASSW:}" // if PASSW is not defined would result in password === '' * + * If you want to use an empty value (null) as default value for a variable, + * simply do not set it, without putting any colons: "${ABIWORD}". + * + * 3) if you want to use newlines in the default value of a string parameter, + * use "\n" as usual. + * + * "defaultPadText" : "${DEFAULT_PAD_TEXT}Line 1\nLine 2" */ { /* @@ -92,7 +99,40 @@ "skinName": "${SKIN_NAME:colibris}", /* - * IP and port which etherpad should bind at + * Skin Variants + * + * Use the UI skin variants builder at /p/test#skinvariantsbuilder + * + * For the colibris skin only, you can choose how to render the three main + * containers: + * - toolbar (top menu with icons) + * - editor (containing the text of the pad) + * - background (area outside of editor, mostly visible when using page style) + * + * For each of the 3 containers you can choose 4 color combinations: + * super-light, light, dark, super-dark. + * + * For example, to make the toolbar dark, you will include "dark-toolbar" into + * skinVariants. + * + * You can provide multiple skin variants separated by spaces. Default + * skinVariant is "super-light-toolbar super-light-editor light-background". + * + * For the editor container, you can also make it full width by adding + * "full-width-editor" variant (by default editor is rendered as a page, with + * a max-width of 900px). + */ + "skinVariants": "${SKIN_VARIANTS:super-light-toolbar super-light-editor light-background}", + + /* + * IP and port which Etherpad should bind at. + * + * Binding to a Unix socket is also supported: just use an empty string for + * the ip, and put the full path to the socket in the port parameter. + * + * EXAMPLE USING UNIX SOCKET: + * "ip": "", // <-- has to be an empty string + * "port" : "/somepath/etherpad.socket", // <-- path to a Unix socket */ "ip": "${IP:0.0.0.0}", "port": "${PORT:9001}", @@ -152,7 +192,7 @@ /* * The default text of a pad */ - "defaultPadText" : "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http:\/\/etherpad.org\n", + "defaultPadText" : "${DEFAULT_PAD_TEXT:Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at https:\/\/etherpad.org\n}", /* * Default Pad behavior. @@ -160,57 +200,57 @@ * Change them if you want to override. */ "padOptions": { - "noColors": false, - "showControls": true, - "showChat": true, - "showLineNumbers": true, - "useMonospaceFont": false, - "userName": false, - "userColor": false, - "rtl": false, - "alwaysShowChat": false, - "chatAndUsers": false, - "lang": "en-gb" + "noColors": "${PAD_OPTIONS_NO_COLORS:false}", + "showControls": "${PAD_OPTIONS_SHOW_CONTROLS:true}", + "showChat": "${PAD_OPTIONS_SHOW_CHAT:true}", + "showLineNumbers": "${PAD_OPTIONS_SHOW_LINE_NUMBERS:true}", + "useMonospaceFont": "${PAD_OPTIONS_USE_MONOSPACE_FONT:false}", + "userName": "${PAD_OPTIONS_USER_NAME:false}", + "userColor": "${PAD_OPTIONS_USER_COLOR:false}", + "rtl": "${PAD_OPTIONS_RTL:false}", + "alwaysShowChat": "${PAD_OPTIONS_ALWAYS_SHOW_CHAT:false}", + "chatAndUsers": "${PAD_OPTIONS_CHAT_AND_USERS:false}", + "lang": "${PAD_OPTIONS_LANG:en-gb}" }, /* * Pad Shortcut Keys */ "padShortcutEnabled" : { - "altF9": true, /* focus on the File Menu and/or editbar */ - "altC": true, /* focus on the Chat window */ - "cmdShift2": true, /* shows a gritter popup showing a line author */ - "delete": true, - "return": true, - "esc": true, /* in mozilla versions 14-19 avoid reconnecting pad */ - "cmdS": true, /* save a revision */ - "tab": true, /* indent */ - "cmdZ": true, /* undo/redo */ - "cmdY": true, /* redo */ - "cmdI": true, /* italic */ - "cmdB": true, /* bold */ - "cmdU": true, /* underline */ - "cmd5": true, /* strike through */ - "cmdShiftL": true, /* unordered list */ - "cmdShiftN": true, /* ordered list */ - "cmdShift1": true, /* ordered list */ - "cmdShiftC": true, /* clear authorship */ - "cmdH": true, /* backspace */ - "ctrlHome": true, /* scroll to top of pad */ - "pageUp": true, - "pageDown": true + "altF9": "${PAD_SHORTCUTS_ENABLED_ALT_F9:true}", /* focus on the File Menu and/or editbar */ + "altC": "${PAD_SHORTCUTS_ENABLED_ALT_C:true}", /* focus on the Chat window */ + "cmdShift2": "${PAD_SHORTCUTS_ENABLED_CMD_SHIFT_2:true}", /* shows a gritter popup showing a line author */ + "delete": "${PAD_SHORTCUTS_ENABLED_DELETE:true}", + "return": "${PAD_SHORTCUTS_ENABLED_RETURN:true}", + "esc": "${PAD_SHORTCUTS_ENABLED_ESC:true}", /* in mozilla versions 14-19 avoid reconnecting pad */ + "cmdS": "${PAD_SHORTCUTS_ENABLED_CMD_S:true}", /* save a revision */ + "tab": "${PAD_SHORTCUTS_ENABLED_TAB:true}", /* indent */ + "cmdZ": "${PAD_SHORTCUTS_ENABLED_CMD_Z:true}", /* undo/redo */ + "cmdY": "${PAD_SHORTCUTS_ENABLED_CMD_Y:true}", /* redo */ + "cmdI": "${PAD_SHORTCUTS_ENABLED_CMD_I:true}", /* italic */ + "cmdB": "${PAD_SHORTCUTS_ENABLED_CMD_B:true}", /* bold */ + "cmdU": "${PAD_SHORTCUTS_ENABLED_CMD_U:true}", /* underline */ + "cmd5": "${PAD_SHORTCUTS_ENABLED_CMD_5:true}", /* strike through */ + "cmdShiftL": "${PAD_SHORTCUTS_ENABLED_CMD_SHIFT_L:true}", /* unordered list */ + "cmdShiftN": "${PAD_SHORTCUTS_ENABLED_CMD_SHIFT_N:true}", /* ordered list */ + "cmdShift1": "${PAD_SHORTCUTS_ENABLED_CMD_SHIFT_1:true}", /* ordered list */ + "cmdShiftC": "${PAD_SHORTCUTS_ENABLED_CMD_SHIFT_C:true}", /* clear authorship */ + "cmdH": "${PAD_SHORTCUTS_ENABLED_CMD_H:true}", /* backspace */ + "ctrlHome": "${PAD_SHORTCUTS_ENABLED_CTRL_HOME:true}", /* scroll to top of pad */ + "pageUp": "${PAD_SHORTCUTS_ENABLED_PAGE_UP:true}", + "pageDown": "${PAD_SHORTCUTS_ENABLED_PAGE_DOWN:true}" }, /* * Should we suppress errors from being visible in the default Pad Text? */ - "suppressErrorsInPadText": false, + "suppressErrorsInPadText": "${SUPPRESS_ERRORS_IN_PAD_TEXT:false}", /* * If this option is enabled, a user must have a session to access pads. * This effectively allows only group pads to be accessed. */ - "requireSession": false, + "requireSession": "${REQUIRE_SESSION:false}", /* * Users may edit pads but not create new ones. @@ -218,13 +258,13 @@ * Pad creation is only via the API. * This applies both to group pads and regular pads. */ - "editOnly": false, + "editOnly": "${EDIT_ONLY:false}", /* * If set to true, those users who have a valid session will automatically be * granted access to password protected pads. */ - "sessionNoPassword": false, + "sessionNoPassword": "${SESSION_NO_PASSWORD:false}", /* * If true, all css & js will be minified before sending to the client. @@ -232,7 +272,7 @@ * This will improve the loading performance massively, but makes it difficult * to debug the javascript/css */ - "minify": true, + "minify": "${MINIFY:true}", /* * How long may clients use served javascript code (in seconds)? @@ -240,7 +280,7 @@ * Not setting this may cause problems during deployment. * Set to 0 to disable caching. */ - "maxAge": 21600, // 60 * 60 * 6 = 6 hours + "maxAge": "${MAX_AGE:21600}", // 60 * 60 * 6 = 6 hours /* * Absolute path to the Abiword executable. @@ -249,7 +289,7 @@ * it to null disables Abiword and will only allow plain text and HTML * import/exports. */ - "abiword": null, + "abiword": "${ABIWORD}", /* * This is the absolute path to the soffice executable. @@ -257,7 +297,7 @@ * LibreOffice can be used in lieu of Abiword to export pads. * Setting it to null disables LibreOffice exporting. */ - "soffice": null, + "soffice": "${SOFFICE}", /* * Path to the Tidy executable. @@ -265,25 +305,25 @@ * Tidy is used to improve the quality of exported pads. * Setting it to null disables Tidy. */ - "tidyHtml": null, + "tidyHtml": "${TIDY_HTML}", /* * Allow import of file types other than the supported ones: * txt, doc, docx, rtf, odt, html & htm */ - "allowUnknownFileEnds": true, + "allowUnknownFileEnds": "${ALLOW_UNKNOWN_FILE_ENDS:true}", /* * This setting is used if you require authentication of all users. * * Note: "/admin" always requires authentication. */ - "requireAuthentication": false, + "requireAuthentication": "${REQUIRE_AUTHENTICATION:false}", /* * Require authorization by a module, or a user with is_admin set, see below. */ - "requireAuthorization": false, + "requireAuthorization": "${REQUIRE_AUTHORIZATION:false}", /* * When you use NGINX or another proxy/load-balancer set this to true. @@ -299,7 +339,7 @@ /* * Privacy: disable IP logging */ - "disableIPlogging": false, + "disableIPlogging": "${DISABLE_IP_LOGGING:false}", /* * Time (in seconds) to automatically reconnect pad when a "Force reconnect" @@ -307,7 +347,7 @@ * * Set to 0 to disable automatic reconnection. */ - "automaticReconnectionTimeout": 0, + "automaticReconnectionTimeout": "${AUTOMATIC_RECONNECTION_TIMEOUT:0}", /* * By default, when caret is moved out of viewport, it scrolls the minimum @@ -325,21 +365,21 @@ * Set to 0 to disable extra scrolling */ "percentage": { - "editionAboveViewport": 0, - "editionBelowViewport": 0 + "editionAboveViewport": "${FOCUS_LINE_PERCENTAGE_ABOVE:0}", + "editionBelowViewport": "${FOCUS_LINE_PERCENTAGE_BELOW:0}" }, /* * Time (in milliseconds) used to animate the scroll transition. * Set to 0 to disable animation */ - "duration": 0, + "duration": "${FOCUS_LINE_DURATION:0}", /* * Flag to control if it should scroll when user places the caret in the * last line of the viewport */ - "scrollWhenCaretIsInTheLastLineOfViewport": false, + "scrollWhenCaretIsInTheLastLineOfViewport": "${FOCUS_LINE_CARET_SCROLL:false}", /* * Percentage of viewport height to be additionally scrolled when user @@ -347,7 +387,7 @@ * * Set to 0 to let the scroll to be handled as default by Etherpad */ - "percentageToScrollWhenUserPressesArrowUp": 0 + "percentageToScrollWhenUserPressesArrowUp": "${FOCUS_LINE_PERCENTAGE_ARROW_UP:0}" }, /* @@ -386,7 +426,7 @@ * * WARNING: this will disable security on the instance. */ - "loadTest": false, + "loadTest": "${LOAD_TEST:false}", /* * Disable indentation on new line when previous line ends with some special @@ -397,6 +437,31 @@ "indentationOnNewLine": false, */ + /* + * From Etherpad 1.8.3 onwards, import and export of pads is always rate + * limited. + * + * The default is to allow at most 10 requests per IP in a 90 seconds window. + * After that the import/export request is rejected. + * + * See https://github.com/nfriedly/express-rate-limit for more options + */ + "importExportRateLimiting": { + // duration of the rate limit window (milliseconds) + "windowMs": "${IMPORT_EXPORT_RATE_LIMIT_WINDOW:90000}", + + // maximum number of requests per IP to allow during the rate limit window + "max": "${IMPORT_EXPORT_MAX_REQ_PER_IP:10}" + }, + + /* + * From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported + * file is always bounded. + * + * File size is specified in bytes. Default is 50 MB. + */ + "importMaxFileSize": "${IMPORT_MAX_FILE_SIZE:52428800}", // 50 * 1024 * 1024 + /* * Toolbar buttons configuration. * @@ -427,7 +492,7 @@ * * Do not enable on production machines. */ - "exposeVersion": false, + "exposeVersion": "${EXPOSE_VERSION:false}", /* * The log level we are using. diff --git a/settings.json.template b/settings.json.template index 598f07611c6..f01dc7802c6 100644 --- a/settings.json.template +++ b/settings.json.template @@ -56,6 +56,13 @@ * "password": "${PASSW}" // if PASSW is not defined would result in password === null * "password": "${PASSW:}" // if PASSW is not defined would result in password === '' * + * If you want to use an empty value (null) as default value for a variable, + * simply do not set it, without putting any colons: "${ABIWORD}". + * + * 3) if you want to use newlines in the default value of a string parameter, + * use "\n" as usual. + * + * "defaultPadText" : "${DEFAULT_PAD_TEXT}Line 1\nLine 2" */ { /* @@ -80,10 +87,43 @@ * - "colibris": the new experimental skin (since Etherpad 1.8), candidate to * become the default in Etherpad 2.0 */ - "skinName": "no-skin", + "skinName": "colibris", + + /* + * Skin Variants + * + * Use the UI skin variants builder at /p/test#skinvariantsbuilder + * + * For the colibris skin only, you can choose how to render the three main + * containers: + * - toolbar (top menu with icons) + * - editor (containing the text of the pad) + * - background (area outside of editor, mostly visible when using page style) + * + * For each of the 3 containers you can choose 4 color combinations: + * super-light, light, dark, super-dark. + * + * For example, to make the toolbar dark, you will include "dark-toolbar" into + * skinVariants. + * + * You can provide multiple skin variants separated by spaces. Default + * skinVariant is "super-light-toolbar super-light-editor light-background". + * + * For the editor container, you can also make it full width by adding + * "full-width-editor" variant (by default editor is rendered as a page, with + * a max-width of 900px). + */ + "skinVariants": "super-light-toolbar super-light-editor light-background", /* - * IP and port which etherpad should bind at + * IP and port which Etherpad should bind at. + * + * Binding to a Unix socket is also supported: just use an empty string for + * the ip, and put the full path to the socket in the port parameter. + * + * EXAMPLE USING UNIX SOCKET: + * "ip": "", // <-- has to be an empty string + * "port" : "/somepath/etherpad.socket", // <-- path to a Unix socket */ "ip": "0.0.0.0", "port": 9001, @@ -155,7 +195,7 @@ /* * The default text of a pad */ - "defaultPadText" : "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http:\/\/etherpad.org\n", + "defaultPadText" : "Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at https:\/\/etherpad.org\n", /* * Default Pad behavior. @@ -402,6 +442,31 @@ "indentationOnNewLine": false, */ + /* + * From Etherpad 1.8.3 onwards, import and export of pads is always rate + * limited. + * + * The default is to allow at most 10 requests per IP in a 90 seconds window. + * After that the import/export request is rejected. + * + * See https://github.com/nfriedly/express-rate-limit for more options + */ + "importExportRateLimiting": { + // duration of the rate limit window (milliseconds) + "windowMs": 90000, + + // maximum number of requests per IP to allow during the rate limit window + "max": 10 + }, + + /* + * From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported + * file is always bounded. + * + * File size is specified in bytes. Default is 50 MB. + */ + "importMaxFileSize": 52428800, // 50 * 1024 * 1024 + /* * Toolbar buttons configuration. * diff --git a/src/ep.json b/src/ep.json index eeb5c640913..428f57269a8 100644 --- a/src/ep.json +++ b/src/ep.json @@ -18,12 +18,12 @@ { "name": "admin", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/admin:expressCreateServer" } }, { "name": "adminplugins", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminplugins:expressCreateServer", - "socketio": "ep_etherpad-lite/node/hooks/express/adminplugins:socketio" } + "socketio": "ep_etherpad-lite/node/hooks/express/adminplugins:socketio" } }, { "name": "adminsettings", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminsettings:expressCreateServer", "socketio": "ep_etherpad-lite/node/hooks/express/adminsettings:socketio" } }, - { "name": "swagger", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/swagger:expressCreateServer" } } + { "name": "openapi", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/openapi:expressCreateServer" } } ] } diff --git a/src/etherpad_icon.svg b/src/etherpad_icon.svg index ebdcde99b64..876db0fe0eb 100644 --- a/src/etherpad_icon.svg +++ b/src/etherpad_icon.svg @@ -7,10 +7,38 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" version="1.1" width="16" height="16" - id="svg2987"> + id="svg2987" + sodipodi:docname="etherpad_icon.svg" + inkscape:version="0.92.1 r15371" + inkscape:export-filename="/home/websites/etherpad-lite/src/static/favicon.ico.png" + inkscape:export-xdpi="96" + inkscape:export-ydpi="96"> + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/src/locales/af.json b/src/locales/af.json index 1a9ce4cc451..37cf13ef4ac 100644 --- a/src/locales/af.json +++ b/src/locales/af.json @@ -1,8 +1,8 @@ { "@metadata": { "authors": [ - "Naudefj", - "Fwolff" + "Fwolff", + "Naudefj" ] }, "index.newPad": "Nuwe pad", @@ -25,7 +25,6 @@ "pad.loading": "Laai...", "pad.settings.myView": "My oorsig", "pad.settings.fontType.normal": "Normaal", - "pad.settings.fontType.monospaced": "Monospasie", "pad.settings.language": "Taal:", "pad.importExport.import_export": "Voer in/uit", "pad.importExport.import": "Laai enige tekslêer of dokument op", diff --git a/src/locales/ar.json b/src/locales/ar.json index b332508b2bc..9c6d5a435ce 100644 --- a/src/locales/ar.json +++ b/src/locales/ar.json @@ -1,16 +1,17 @@ { "@metadata": { "authors": [ - "Ali1", - "Tux-tn", "Alami", + "Ali1", + "Haytham morsy", "Meno25", + "Mido", + "Shbib Al-Subaie", + "Tala Ali", "Test Create account", - "محمد أحمد عبد الفتاح", - "Haytham morsy", + "Tux-tn", "ديفيد", - "Mido", - "Shbib Al-Subaie" + "محمد أحمد عبد الفتاح" ] }, "index.newPad": "باد جديد", @@ -48,8 +49,6 @@ "pad.settings.rtlcheck": "قراءة المحتويات من اليمين إلى اليسار؟", "pad.settings.fontType": "نوع الخط:", "pad.settings.fontType.normal": "عادي", - "pad.settings.fontType.monospaced": "ثابت العرض", - "pad.settings.globalView": "الرؤية الشاملة", "pad.settings.language": "اللغة:", "pad.importExport.import_export": "استيراد/تصدير", "pad.importExport.import": "تحميل أي ملف نصي أو وثيقة", @@ -129,7 +128,7 @@ "pad.userlist.guest": "ضيف", "pad.userlist.deny": "رفض", "pad.userlist.approve": "موافقة", - "pad.editbar.clearcolors": "مسح ألوان التأليف أو المستند بأكمله؟", + "pad.editbar.clearcolors": "مسح ألوان التأليف أو المستند بأكمله؟ هذا لا يمكن التراجع عنه", "pad.impexp.importbutton": "الاستيراد الآن", "pad.impexp.importing": "الاستيراد...", "pad.impexp.confirmimport": "استيراد ملف سيؤدي للكتابة فوق النص الحالي بالباد. هل أنت متأكد من أنك تريد المتابعة؟", diff --git a/src/locales/ast.json b/src/locales/ast.json index 17bc975867f..a8beb80f5d4 100644 --- a/src/locales/ast.json +++ b/src/locales/ast.json @@ -39,8 +39,6 @@ "pad.settings.rtlcheck": "¿Lleer el conteníu de drecha a izquierda?", "pad.settings.fontType": "Tipografía:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monoespaciada", - "pad.settings.globalView": "Vista global", "pad.settings.language": "Llingua:", "pad.importExport.import_export": "Importar/Esportar", "pad.importExport.import": "Xubir cualquier ficheru o documentu de testu", @@ -120,7 +118,7 @@ "pad.userlist.guest": "Invitáu", "pad.userlist.deny": "Refugar", "pad.userlist.approve": "Aprobar", - "pad.editbar.clearcolors": "¿Llimpiar los colores d'autoría nel documentu ensembre?", + "pad.editbar.clearcolors": "¿Llimpiar los colores d'autoría nel documentu ensembre? Esto nun pue desfacese", "pad.impexp.importbutton": "Importar agora", "pad.impexp.importing": "Importando...", "pad.impexp.confirmimport": "La importación d'un ficheru sustituirá'l testu actual del bloc. ¿Seguro que quies siguir?", diff --git a/src/locales/awa.json b/src/locales/awa.json index f8c0d501c3c..40f66e14230 100644 --- a/src/locales/awa.json +++ b/src/locales/awa.json @@ -25,8 +25,6 @@ "pad.settings.linenocheck": "हरफ संख्या", "pad.settings.fontType": "फन्ट प्रकार:", "pad.settings.fontType.normal": "साधारण", - "pad.settings.fontType.monospaced": "मोनोस्पेस", - "pad.settings.globalView": "विश्वव्यापी दृष्य", "pad.settings.language": "भाषा", "pad.importExport.import_export": "आयात/निर्यात", "pad.importExport.importSuccessful": "सफल!", diff --git a/src/locales/az.json b/src/locales/az.json index 97270649eaa..6a34fe7dd02 100644 --- a/src/locales/az.json +++ b/src/locales/az.json @@ -2,12 +2,12 @@ "@metadata": { "authors": [ "AZISS", + "Archaeodontosaurus", "Khan27", - "Mushviq Abdulla", - "Wertuose", "Mastizada", - "Archaeodontosaurus", - "Neriman2003" + "Mushviq Abdulla", + "Neriman2003", + "Wertuose" ] }, "index.newPad": "Yeni lövhə", @@ -45,8 +45,6 @@ "pad.settings.rtlcheck": "Mühtəviyyat sağdan sola doğru oxunsunmu?", "pad.settings.fontType": "Şriftin tipi:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monoboşluq", - "pad.settings.globalView": "Ümumi görünüş", "pad.settings.language": "Dil:", "pad.importExport.import_export": "İdxal/İxrac", "pad.importExport.import": "Hər hansı bir mətn faylı və ya sənəd yüklə", @@ -92,6 +90,8 @@ "pad.chat": "Söhbət", "pad.chat.title": "Bu lövhə üçün çat açın.", "pad.chat.loadmessages": "Daha çox mesaj yüklə", + "pad.chat.stick.title": "Yazışmanı ekrana kilidlə", + "pad.chat.writeMessage.placeholder": "Mesajını bura yaz", "timeslider.pageTitle": "{{appTitle}} Vaxt cədvəli", "timeslider.toolbar.returnbutton": "Lövhəyə qayıt", "timeslider.toolbar.authors": "Müəlliflər:", diff --git a/src/locales/azb.json b/src/locales/azb.json index 4eeec317d14..7da2c612261 100644 --- a/src/locales/azb.json +++ b/src/locales/azb.json @@ -1,11 +1,11 @@ { "@metadata": { "authors": [ + "Alp Er Tunqa", "Amir a57", - "Mousa", + "Ilğım", "Koroğlu", - "Alp Er Tunqa", - "Ilğım" + "Mousa" ] }, "index.newPad": "یئنی یادداشت دفترچه سی", @@ -43,8 +43,6 @@ "pad.settings.rtlcheck": "ایچینده کیلری ساغدان یوخسا سولدان اوخوسون؟", "pad.settings.fontType": "قلم نوعی", "pad.settings.fontType.normal": "نورمال", - "pad.settings.fontType.monospaced": "مونو اسپئیس", - "pad.settings.globalView": "سراسر گورونتو", "pad.settings.language": "دیل:", "pad.importExport.import_export": "ایچری توکمه /ائشیگه توکمه", "pad.importExport.import": "سند یا دا متنی پرونده یوکله", diff --git a/src/locales/bcc.json b/src/locales/bcc.json index a63e2a2ebef..a91048951ed 100644 --- a/src/locales/bcc.json +++ b/src/locales/bcc.json @@ -38,8 +38,6 @@ "pad.settings.rtlcheck": "خواندن محتوا از راست به چپ؟", "pad.settings.fontType": "نوع قلم:", "pad.settings.fontType.normal": "نرمال", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "نمای سراسری", "pad.settings.language": "زبان:", "pad.importExport.import_export": "درون‌ریزی/برون‌ریزی", "pad.importExport.import": "بارگذاری پرونده‌ی متنی یا سند", diff --git a/src/locales/be-tarask.json b/src/locales/be-tarask.json index d29f9cb204f..d96bc9af197 100644 --- a/src/locales/be-tarask.json +++ b/src/locales/be-tarask.json @@ -2,8 +2,8 @@ "@metadata": { "authors": [ "Jim-by", - "Wizardist", - "Red Winged Duck" + "Red Winged Duck", + "Wizardist" ] }, "index.newPad": "Стварыць", @@ -41,8 +41,6 @@ "pad.settings.rtlcheck": "Тэкст справа-налева", "pad.settings.fontType": "Тып шрыфту:", "pad.settings.fontType.normal": "Звычайны", - "pad.settings.fontType.monospaced": "Монашырынны", - "pad.settings.globalView": "Агульны выгляд", "pad.settings.language": "Мова:", "pad.importExport.import_export": "Імпарт/Экспарт", "pad.importExport.import": "Загрузіжайце любыя тэкставыя файлы або дакумэнты", diff --git a/src/locales/bg.json b/src/locales/bg.json index 2a22b5230e3..5caf2bdff72 100644 --- a/src/locales/bg.json +++ b/src/locales/bg.json @@ -1,9 +1,9 @@ { "@metadata": { "authors": [ - "Vodnokon4e", "StanProg", - "Vlad5250" + "Vlad5250", + "Vodnokon4e" ] }, "index.newPad": "Нов пад", diff --git a/src/locales/bgn.json b/src/locales/bgn.json index 00efbf3f96b..148d981c18e 100644 --- a/src/locales/bgn.json +++ b/src/locales/bgn.json @@ -33,8 +33,6 @@ "pad.settings.rtlcheck": "محتوایی وانتین شه راست بی چپا؟", "pad.settings.fontType": "قلم رکم:", "pad.settings.fontType.normal": "ساددگ", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "سراسرین دیست یا نما", "pad.settings.language": "زبان:", "pad.importExport.exporthtml": "HTML", "pad.importExport.exportplain": "ساده گین متن", diff --git a/src/locales/bn.json b/src/locales/bn.json index 42dae70b7dc..bba3f8caeef 100644 --- a/src/locales/bn.json +++ b/src/locales/bn.json @@ -1,11 +1,11 @@ { "@metadata": { "authors": [ + "Aftab1995", + "Aftabuzzaman", "Bellayet", "Nasir8891", "Sankarshan", - "Aftab1995", - "Aftabuzzaman", "আফতাবুজ্জামান" ] }, @@ -44,8 +44,6 @@ "pad.settings.rtlcheck": "ডান থেকে বামে বিষয়বস্তু পড়বেন?", "pad.settings.fontType": "ফন্টের প্রকার:", "pad.settings.fontType.normal": "সাধারণ", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "সর্বব্যাপী দৃশ্য", "pad.settings.language": "ভাষা:", "pad.importExport.import_export": "আমদানি/রপ্তানি", "pad.importExport.import": "কোন টেক্সট ফাইল বা নথি আপলোড করুন", diff --git a/src/locales/br.json b/src/locales/br.json index b020f963094..f38ce24784b 100644 --- a/src/locales/br.json +++ b/src/locales/br.json @@ -42,8 +42,6 @@ "pad.settings.rtlcheck": "Lenn an danvez a-zehou da gleiz ?", "pad.settings.fontType": "Seurt font :", "pad.settings.fontType.normal": "Reizh", - "pad.settings.fontType.monospaced": "Monospas", - "pad.settings.globalView": "Gwel dre vras", "pad.settings.language": "Yezh :", "pad.importExport.import_export": "Enporzhiañ/Ezporzhiañ", "pad.importExport.import": "Enkargañ un destenn pe ur restr", @@ -123,7 +121,7 @@ "pad.userlist.guest": "Den pedet", "pad.userlist.deny": "Nac'h", "pad.userlist.approve": "Aprouiñ", - "pad.editbar.clearcolors": "Diverkañ al livioù stag ouzh an aozerien en teul a-bezh ?", + "pad.editbar.clearcolors": "Diverkañ al livioù stag ouzh an aozerien en teul a-bezh ? Ne c'hallo ket bezañ disc'hraet", "pad.impexp.importbutton": "Enporzhiañ bremañ", "pad.impexp.importing": "Oc'h enporzhiañ...", "pad.impexp.confirmimport": "Ma vez enporzhiet ur restr e vo diverket ar pezh zo en teul a-vremañ. Ha sur oc'h e fell deoc'h mont betek penn ?", diff --git a/src/locales/bs.json b/src/locales/bs.json index 85c6979e4b5..59283c85f62 100644 --- a/src/locales/bs.json +++ b/src/locales/bs.json @@ -2,8 +2,8 @@ "@metadata": { "authors": [ "Edinwiki", - "Srdjan m", - "Semina x" + "Semina x", + "Srdjan m" ] }, "index.newPad": "Novi Pad", @@ -40,7 +40,6 @@ "pad.settings.rtlcheck": "Da prikažem sadržaj zdesna ulijevo?", "pad.settings.fontType": "Vrsta fonta:", "pad.settings.fontType.normal": "Normalno", - "pad.settings.globalView": "Globalni prikaz", "pad.settings.language": "Jezik:", "pad.importExport.import_export": "Uvoz/Izvoz", "pad.importExport.import": "Postavite bilo koju tekstualnu datoteku ili dokument", diff --git a/src/locales/ca.json b/src/locales/ca.json index 3b0eba48bed..7afdc934fe2 100644 --- a/src/locales/ca.json +++ b/src/locales/ca.json @@ -2,14 +2,14 @@ "@metadata": { "authors": [ "Alvaro Vidal-Abarca", - "Pginer", - "Pitort", - "Toniher", - "Macofe", - "Joan manel", "Eduardo Martinez", "Jaumeortola", - "Ssola" + "Joan manel", + "Macofe", + "Pginer", + "Pitort", + "Ssola", + "Toniher" ] }, "index.newPad": "Nou pad", @@ -47,8 +47,6 @@ "pad.settings.rtlcheck": "Llegir el contingut de dreta a esquerra?", "pad.settings.fontType": "Tipus de lletra:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "D'amplada fixa", - "pad.settings.globalView": "Vista global", "pad.settings.language": "Llengua:", "pad.importExport.import_export": "Importació/exportació", "pad.importExport.import": "Puja qualsevol fitxer de text o document", diff --git a/src/locales/cs.json b/src/locales/cs.json index 10fc55e1729..2896f91a6fe 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -1,15 +1,16 @@ { "@metadata": { "authors": [ + "Aktron", + "Clon", + "Dvorapa", "Jakubt", "Jezevec", "Juandev", "Leanes", - "Quinn", - "Aktron", "Mormegil", - "Dvorapa", - "Clon" + "Peldrjan", + "Quinn" ] }, "index.newPad": "Založ nový Pad", @@ -47,8 +48,6 @@ "pad.settings.rtlcheck": "Číst obsah zprava doleva?", "pad.settings.fontType": "Typ písma:", "pad.settings.fontType.normal": "Normální", - "pad.settings.fontType.monospaced": "Neproporční", - "pad.settings.globalView": "Globální pohled", "pad.settings.language": "Jazyk:", "pad.importExport.import_export": "Import/Export", "pad.importExport.import": "Nahrát libovolný textový soubor nebo dokument", @@ -64,7 +63,7 @@ "pad.modals.connected": "Připojeno.", "pad.modals.reconnecting": "Znovupřipojování k Padu…", "pad.modals.forcereconnect": "Vynutit znovupřipojení", - "pad.modals.reconnecttimer": "Zkouším to znovu připojit", + "pad.modals.reconnecttimer": "Zkouším se znovu připojit", "pad.modals.cancel": "Zrušit", "pad.modals.userdup": "Otevřeno v jiném okně", "pad.modals.userdup.explanation": "Zdá se, že tento Pad je na tomto počítači otevřen ve více než jednom okně.", @@ -94,6 +93,8 @@ "pad.chat": "Chat", "pad.chat.title": "Otevřít chat tohoto Padu.", "pad.chat.loadmessages": "Načíst více zpráv", + "pad.chat.stick.title": "Přichytit chat k obrazovce", + "pad.chat.writeMessage.placeholder": "Zde napište zprávu", "timeslider.pageTitle": "Časová osa {{appTitle}}", "timeslider.toolbar.returnbutton": "Návrat do Padu", "timeslider.toolbar.authors": "Autoři:", @@ -126,7 +127,7 @@ "pad.userlist.guest": "Host", "pad.userlist.deny": "Zakázat", "pad.userlist.approve": "Povolit", - "pad.editbar.clearcolors": "Odstranit barvy autorů z celého dokumentu?", + "pad.editbar.clearcolors": "Odstranit barvy autorů z celého dokumentu? Tuto změnu nelze vrátit!", "pad.impexp.importbutton": "Importovat", "pad.impexp.importing": "Importování…", "pad.impexp.confirmimport": "Import souboru přepíše aktuální text v padu. Opravdu chcete tuto akci provést?", diff --git a/src/locales/da.json b/src/locales/da.json index 612cd981559..9fe4c1020f1 100644 --- a/src/locales/da.json +++ b/src/locales/da.json @@ -2,10 +2,10 @@ "@metadata": { "authors": [ "Christian List", - "Peter Alberti", - "Steenth", "Joedalton", - "Saederup92" + "Peter Alberti", + "Saederup92", + "Steenth" ] }, "index.newPad": "Ny Pad", @@ -43,9 +43,6 @@ "pad.settings.rtlcheck": "Læse indhold fra højre mod venstre?", "pad.settings.fontType": "Skrifttype:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Fastbredde", - "pad.settings.fontType.trebuchet": "Blide", - "pad.settings.globalView": "Global visning", "pad.settings.language": "Sprog:", "pad.importExport.import_export": "Import/Eksport", "pad.importExport.import": "Uploade en tekstfil eller dokument", diff --git a/src/locales/de.json b/src/locales/de.json index 5bbbb9b1b57..5015eff9a0d 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -4,10 +4,10 @@ "Metalhead64", "Mklehr", "Nipsky", - "Wikinaut", - "Thargon", "Predatorix", - "Sebastian Wallroth" + "Sebastian Wallroth", + "Thargon", + "Wikinaut" ] }, "index.newPad": "Neues Pad", @@ -45,8 +45,6 @@ "pad.settings.rtlcheck": "Inhalt von rechts nach links lesen?", "pad.settings.fontType": "Schriftart:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Gemeinsame Ansicht", "pad.settings.language": "Sprache:", "pad.importExport.import_export": "Import/Export", "pad.importExport.import": "Text-Datei oder Dokument hochladen", diff --git a/src/locales/diq.json b/src/locales/diq.json index 9475c68ae10..cbf2f12fc42 100644 --- a/src/locales/diq.json +++ b/src/locales/diq.json @@ -1,12 +1,12 @@ { "@metadata": { "authors": [ + "1917 Ekim Devrimi", "Erdemaslancan", "Gorizon", - "Mirzali", - "Kumkumuk", - "1917 Ekim Devrimi", "Gırd", + "Kumkumuk", + "Mirzali", "Orbot707" ] }, @@ -45,8 +45,6 @@ "pad.settings.rtlcheck": "Zerrek heto raşt ra be heto çep bıwaniyo?", "pad.settings.fontType": "Babeta nuşti:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Yewca", - "pad.settings.globalView": "Asayışo Global", "pad.settings.language": "Zıwan:", "pad.importExport.import_export": "Zerredayış/Teberdayış", "pad.importExport.import": "Dosya ya zi dokumanê meqaleyê de tesadufi bar ke", @@ -126,7 +124,7 @@ "pad.userlist.guest": "Meyman", "pad.userlist.deny": "Red ke", "pad.userlist.approve": "Tesdiq ke", - "pad.editbar.clearcolors": "Wesiqa de renge nuştoğey bıesterneye?", + "pad.editbar.clearcolors": "Wesiqa de renge nuştoğey bıesternê yê? No kar peyser nêgêrêno", "pad.impexp.importbutton": "Nıka miyan ke", "pad.impexp.importing": "Deyeno azere...", "pad.impexp.confirmimport": "Yu dosya azere kerdış de mewcud bloknoti sero nuşiye no. Şıma qayılê dewam bıkerê?", diff --git a/src/locales/dsb.json b/src/locales/dsb.json index 0600be900a6..4e042c314b5 100644 --- a/src/locales/dsb.json +++ b/src/locales/dsb.json @@ -37,8 +37,6 @@ "pad.settings.rtlcheck": "Wopśimjeśe wótpšawa nalěwo cytaś?", "pad.settings.fontType": "Pismowa družyna:", "pad.settings.fontType.normal": "Normalny", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Globalny naglěd", "pad.settings.language": "Rěc:", "pad.importExport.import_export": "Import/Eksport", "pad.importExport.import": "Tekstowu dataju abo dokument nagraś", diff --git a/src/locales/dty.json b/src/locales/dty.json index 0682da67a3f..8c07fc0c374 100644 --- a/src/locales/dty.json +++ b/src/locales/dty.json @@ -1,9 +1,9 @@ { "@metadata": { "authors": [ + "Nirajan pant", "रमेश सिंह बोहरा", - "राम प्रसाद जोशी", - "Nirajan pant" + "राम प्रसाद जोशी" ] }, "index.newPad": "नौलो प्याड", @@ -40,7 +40,6 @@ "pad.settings.linenocheck": "हरफ संख्या", "pad.settings.rtlcheck": "सामग्री दाहिना बठे देब्रे पढ्न्या हो कि?", "pad.settings.fontType": "फन्ट प्रकार:", - "pad.settings.globalView": "विश्वव्यापी दृष्य", "pad.settings.language": "भाषा:", "pad.importExport.import_export": "आयात/निर्यात", "pad.importExport.import": "कोइलै पाठ फाइल और कागजात अपलोड अरऽ", diff --git a/src/locales/el.json b/src/locales/el.json index 2c9d378e86b..7b7735b6323 100644 --- a/src/locales/el.json +++ b/src/locales/el.json @@ -43,8 +43,6 @@ "pad.settings.rtlcheck": "Διαβάζεται το περιεχόμενο από δεξιά προς τα αριστερά;", "pad.settings.fontType": "Τύπος γραμματοσειράς:", "pad.settings.fontType.normal": "Κανονική", - "pad.settings.fontType.monospaced": "Καθορισμένου πλάτους", - "pad.settings.globalView": "Καθολική Προβολή", "pad.settings.language": "Γλώσσα:", "pad.importExport.import_export": "Εισαγωγή/Εξαγωγή", "pad.importExport.import": "Αποστολή οποιουδήποτε αρχείου κειμένου ή εγγράφου", diff --git a/src/locales/en-gb.json b/src/locales/en-gb.json index f6199e4fe82..37d7ee01bb8 100644 --- a/src/locales/en-gb.json +++ b/src/locales/en-gb.json @@ -1,11 +1,11 @@ { "@metadata": { "authors": [ - "Chase me ladies, I'm the Cavalry", - "Shirayuki", "Andibing", + "Cblair91", + "Chase me ladies, I'm the Cavalry", "HairyFotr", - "Cblair91" + "Shirayuki" ] }, "index.newPad": "New Pad", @@ -43,8 +43,6 @@ "pad.settings.rtlcheck": "Read content from right to left?", "pad.settings.fontType": "Font type:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Global View", "pad.settings.language": "Language:", "pad.importExport.import_export": "Import/Export", "pad.importExport.import": "Upload any text file or document", diff --git a/src/locales/en.json b/src/locales/en.json index c8ef1a7ae4e..fab3c6d2b44 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -38,27 +38,6 @@ "pad.settings.rtlcheck": "Read content from right to left?", "pad.settings.fontType": "Font type:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.opendyslexic": "Open Dyslexic", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.fontType.montserrat": "Montserrat", - "pad.settings.fontType.comicsans": "Comic Sans", - "pad.settings.fontType.couriernew": "Courier New", - "pad.settings.fontType.georgia": "Georgia", - "pad.settings.fontType.impact": "Impact", - "pad.settings.fontType.lucida": "Lucida", - "pad.settings.fontType.lucidasans": "Lucida Sans", - "pad.settings.fontType.palatino": "Palatino", - "pad.settings.fontType.robotomono": "RobotoMono", - "pad.settings.fontType.tahoma": "Tahoma", - "pad.settings.fontType.timesnewroman": "Times New Roman", - "pad.settings.fontType.trebuchet": "Trebuchet", - "pad.settings.fontType.verdana": "Verdana", - "pad.settings.fontType.symbol": "Symbol", - "pad.settings.fontType.webdings": "Webdings", - "pad.settings.fontType.wingdings": "Wingdings", - "pad.settings.fontType.sansserif": "Sans Serif", - "pad.settings.fontType.serif": "Serif", - "pad.settings.globalView": "Global View", "pad.settings.language": "Language:", "pad.importExport.import_export": "Import/Export", @@ -71,7 +50,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.abiword.innerHTML": "You only can import from plain text or HTML formats. For more advanced import features please install AbiWord.", + "pad.importExport.abiword.innerHTML": "You only can import from plain text or HTML formats. For more advanced import features please install AbiWord or LibreOffice.", "pad.modals.connected": "Connected.", "pad.modals.reconnecting": "Reconnecting to your pad..", @@ -154,7 +133,7 @@ "pad.userlist.guest": "Guest", "pad.userlist.deny": "Deny", "pad.userlist.approve": "Approve", - "pad.editbar.clearcolors": "Clear authorship colors on entire document?", + "pad.editbar.clearcolors": "Clear authorship colors on entire document? This cannot be undone", "pad.impexp.importbutton": "Import Now", "pad.impexp.importing": "Importing...", @@ -164,5 +143,7 @@ "pad.impexp.uploadFailed": "The upload failed, please try again", "pad.impexp.importfailed": "Import failed", "pad.impexp.copypaste": "Please copy paste", - "pad.impexp.exportdisabled": "Exporting as {{type}} format is disabled. Please contact your system administrator for details." + "pad.impexp.exportdisabled": "Exporting as {{type}} format is disabled. Please contact your system administrator for details.", + "pad.impexp.maxFileSize": "File too big. Contact your site administrator to increase the allowed file size for import", + "pad.impexp.permission": "Import is disabled because you never contributed to this pad. Please contribute at least once before importing" } diff --git a/src/locales/eo.json b/src/locales/eo.json index a56719ab3c2..6f8428a97a8 100644 --- a/src/locales/eo.json +++ b/src/locales/eo.json @@ -2,10 +2,10 @@ "@metadata": { "authors": [ "Eliovir", + "Mirin", "Mschmitt", "Objectivesea", - "Robin van der Vliet", - "Mirin" + "Robin van der Vliet" ] }, "index.newPad": "Nova Teksto", @@ -43,8 +43,6 @@ "pad.settings.rtlcheck": "Legi dekstre-maldekstren?", "pad.settings.fontType": "Tiparo:", "pad.settings.fontType.normal": "Normala", - "pad.settings.fontType.monospaced": "Egallarĝa", - "pad.settings.globalView": "Ĉiea Vido", "pad.settings.language": "Lingvo:", "pad.importExport.import_export": "Enporti/Elporti", "pad.importExport.import": "Alŝuti ajnan dosieron aŭ dokumenton", diff --git a/src/locales/es.json b/src/locales/es.json index c22803f3eba..126f21e670a 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -2,19 +2,20 @@ "@metadata": { "authors": [ "Armando-Martin", + "Dgstranz", + "Fitoschido", "Jacobo", "Joker", "Larjona", + "Luzcaru", + "Macofe", + "MartaEgea", "Mklehr", "Rubenwap", + "Tiberius1701", "VegaDark", "Vivaelcelta", - "Xuacu", - "Macofe", - "Fitoschido", - "Dgstranz", - "Luzcaru", - "Tiberius1701" + "Xuacu" ] }, "index.newPad": "Nuevo pad", @@ -52,8 +53,6 @@ "pad.settings.rtlcheck": "¿Leer contenido de derecha a izquierda?", "pad.settings.fontType": "Tipografía:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monoespacio", - "pad.settings.globalView": "Preferencias globales", "pad.settings.language": "Idioma:", "pad.importExport.import_export": "Importar/Exportar", "pad.importExport.import": "Subir cualquier texto o documento", @@ -133,7 +132,7 @@ "pad.userlist.guest": "Invitado", "pad.userlist.deny": "Denegar", "pad.userlist.approve": "Aprobar", - "pad.editbar.clearcolors": "¿Quieres borrar los colores de autoría en todo el documento?", + "pad.editbar.clearcolors": "¿Desea borrar los colores de autoría en todo el documento? Esto no se puede deshacer", "pad.impexp.importbutton": "Importar ahora", "pad.impexp.importing": "Importando...", "pad.impexp.confirmimport": "Al importar un archivo se borrará el contenido actual del pad. ¿Estás seguro de que quieres continuar?", diff --git a/src/locales/et.json b/src/locales/et.json index 84430daf77d..4170f65b3cc 100644 --- a/src/locales/et.json +++ b/src/locales/et.json @@ -38,8 +38,6 @@ "pad.settings.rtlcheck": "Näita sisu paremalt vasakule?", "pad.settings.fontType": "Šrifti tüüp:", "pad.settings.fontType.normal": "Normaalne", - "pad.settings.fontType.monospaced": "Ühelaiuste märkidega", - "pad.settings.globalView": "Koguvaade", "pad.settings.language": "Keel:", "pad.importExport.import_export": "Import-eksport", "pad.importExport.import": "Laadi üles mistahes tekstifail või dokument", diff --git a/src/locales/eu.json b/src/locales/eu.json index f8ebb9cdacd..1b8ae12b7e5 100644 --- a/src/locales/eu.json +++ b/src/locales/eu.json @@ -1,12 +1,12 @@ { "@metadata": { "authors": [ - "Theklan", - "Subi", - "Xabier Armendaritz", "An13sa", + "HairyFotr", "Mikel Ibaiba", - "HairyFotr" + "Subi", + "Theklan", + "Xabier Armendaritz" ] }, "index.newPad": "Pad berria", @@ -44,8 +44,6 @@ "pad.settings.rtlcheck": "Edukia eskubitik ezkerrera irakurri?", "pad.settings.fontType": "Tipografia:", "pad.settings.fontType.normal": "Arrunta", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Ikuspegi Globala", "pad.settings.language": "Hizkuntza:", "pad.importExport.import_export": "Inportatu/Esportatu", "pad.importExport.import": "Igo edozein testu fitxategi edo dokumentu", diff --git a/src/locales/fa.json b/src/locales/fa.json index 099d6759405..20dddb00977 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -4,11 +4,11 @@ "BMRG14", "Dalba", "Ebraminio", + "FarsiNevis", + "Omid.koli", "Reza1615", "ZxxZxxZ", - "الناز", - "Omid.koli", - "FarsiNevis" + "الناز" ] }, "index.newPad": "دفترچه یادداشت تازه", @@ -46,8 +46,6 @@ "pad.settings.rtlcheck": "خواندن محتوا از راست به چپ؟", "pad.settings.fontType": "نوع قلم:", "pad.settings.fontType.normal": "ساده", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "نمای سراسری", "pad.settings.language": "زبان:", "pad.importExport.import_export": "درون‌ریزی/برون‌ریزی", "pad.importExport.import": "بارگذاری پرونده‌ی متنی یا سند", diff --git a/src/locales/fi.json b/src/locales/fi.json index 0a8e43fb631..72289177930 100644 --- a/src/locales/fi.json +++ b/src/locales/fi.json @@ -2,19 +2,19 @@ "@metadata": { "authors": [ "Artnay", + "Espeox", "Jl", "Lliehu", + "Macofe", + "MrTapsa", "Nedergard", "Nike", + "Pyscowicz", + "Silvonen", "Stryn", "Tomi Toivio", "Veikk0.ma", - "VezonThunder", - "Macofe", - "MrTapsa", - "Silvonen", - "Espeox", - "Pyscowicz" + "VezonThunder" ] }, "index.newPad": "Uusi muistio", @@ -52,8 +52,6 @@ "pad.settings.rtlcheck": "Luetaanko sisältö oikealta vasemmalle?", "pad.settings.fontType": "Fonttityyppi:", "pad.settings.fontType.normal": "normaali", - "pad.settings.fontType.monospaced": "tasalevyinen", - "pad.settings.globalView": "Yleisnäkymä", "pad.settings.language": "Kieli:", "pad.importExport.import_export": "Tuonti/vienti", "pad.importExport.import": "Lähetä mikä tahansa tekstitiedosto tai asiakirja", @@ -99,6 +97,8 @@ "pad.chat": "Keskustelu", "pad.chat.title": "Avaa keskustelu nykyisestä muistiosta.", "pad.chat.loadmessages": "Lataa lisää viestejä", + "pad.chat.stick.title": "Liimaa chatti ruutuun", + "pad.chat.writeMessage.placeholder": "Kirjoita viestisi tähän", "timeslider.pageTitle": "{{appTitle}} -aikajana", "timeslider.toolbar.returnbutton": "Palaa muistioon", "timeslider.toolbar.authors": "Tekijät:", diff --git a/src/locales/fo.json b/src/locales/fo.json index 43e9d9f1aed..197d8902f9a 100644 --- a/src/locales/fo.json +++ b/src/locales/fo.json @@ -31,8 +31,6 @@ "pad.settings.rtlcheck": "Vil tú lesa innihaldið frá høgru til vinstu?", "pad.settings.fontType": "Skriftslag:", "pad.settings.fontType.normal": "Vanligt", - "pad.settings.fontType.monospaced": "Føst breidd", - "pad.settings.globalView": "Global sýning", "pad.settings.language": "Mál:", "pad.importExport.import_export": "Innflyt/Útflyt", "pad.importExport.import": "Legg út onkra tekstfílu ella dokument", diff --git a/src/locales/fr.json b/src/locales/fr.json index d1f2a0855f6..e7f3bbf5149 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -1,13 +1,20 @@ { "@metadata": { "authors": [ + "Boniface", + "C13m3n7", "Cquoi", "Crochet.david", + "Envlh", + "Framafan", + "Fylip22", "Gomoko", "Goofy", "Goofy-bz", "Jean-Frédéric", "Leviathan", + "Macofe", + "Maxim21", "McDutchie", "Metroitendo", "Od1n", @@ -16,16 +23,9 @@ "Rastus Vernon", "Stephane Cottin", "Tux-tn", - "Maxim21", - "Boniface", - "Macofe", - "Framafan", - "Fylip22", - "C13m3n7", - "Wladek92", "Urhixidur", - "Envlh", - "Verdy p" + "Verdy p", + "Wladek92" ] }, "index.newPad": "Nouveau bloc-notes", @@ -63,8 +63,6 @@ "pad.settings.rtlcheck": "Le contenu doit-il être lu de droite à gauche ?", "pad.settings.fontType": "Police :", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Vue d’ensemble", "pad.settings.language": "Langue :", "pad.importExport.import_export": "Importer/Exporter", "pad.importExport.import": "Charger un texte ou un document", @@ -144,7 +142,7 @@ "pad.userlist.guest": "Invité", "pad.userlist.deny": "Refuser", "pad.userlist.approve": "Approuver", - "pad.editbar.clearcolors": "Effacer le surlignage par auteur dans tout le document ?", + "pad.editbar.clearcolors": "Effacer le surlignage par auteur dans tout le document ? Cette action ne peut être annulée.", "pad.impexp.importbutton": "Importer maintenant", "pad.impexp.importing": "Import en cours...", "pad.impexp.confirmimport": "Importer un fichier écrasera le contenu actuel du bloc-notes. Êtes-vous sûr de vouloir le faire ?", diff --git a/src/locales/fy.json b/src/locales/fy.json index 540061d695f..ed4d605f732 100644 --- a/src/locales/fy.json +++ b/src/locales/fy.json @@ -11,7 +11,6 @@ "pad.colorpicker.save": "Bewarje", "pad.colorpicker.cancel": "Annulearje", "pad.settings.fontType.normal": "Normaal", - "pad.settings.fontType.monospaced": "Monospace", "pad.settings.language": "Taal:", "pad.importExport.exporthtml": "HTML", "pad.importExport.exportword": "Microsoft Word", diff --git a/src/locales/gl.json b/src/locales/gl.json index a8173379b24..214059b3960 100644 --- a/src/locales/gl.json +++ b/src/locales/gl.json @@ -1,8 +1,8 @@ { "@metadata": { "authors": [ - "Toliño", - "Elisardojm" + "Elisardojm", + "Toliño" ] }, "index.newPad": "Novo documento", @@ -40,8 +40,6 @@ "pad.settings.rtlcheck": "Quere ler o contido da dereita á esquerda?", "pad.settings.fontType": "Tipo de letra:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monoespazada", - "pad.settings.globalView": "Vista global", "pad.settings.language": "Lingua:", "pad.importExport.import_export": "Importar/Exportar", "pad.importExport.import": "Cargar un ficheiro de texto ou documento", diff --git a/src/locales/gu.json b/src/locales/gu.json index 00a1a5fa5b2..b9aee98e6ce 100644 --- a/src/locales/gu.json +++ b/src/locales/gu.json @@ -19,7 +19,6 @@ "pad.settings.padSettings": "પેડ ગોઠવણીઓ", "pad.settings.myView": "મારા મતે", "pad.settings.fontType.normal": "સામાન્ય", - "pad.settings.fontType.monospaced": "મોનોસ્પેસ", "pad.settings.language": "ભાષા:", "pad.importExport.import_export": "આયાત/નિકાસ", "pad.importExport.importSuccessful": "સફળ!", diff --git a/src/locales/he.json b/src/locales/he.json index 01cad9352ae..c93f762a705 100644 --- a/src/locales/he.json +++ b/src/locales/he.json @@ -42,8 +42,6 @@ "pad.settings.rtlcheck": "לקרוא את התוכן מימין לשמאל?", "pad.settings.fontType": "סוג גופן:", "pad.settings.fontType.normal": "רגיל", - "pad.settings.fontType.monospaced": "ברוחב קבוע", - "pad.settings.globalView": "תצוגה לכל המשתמשים", "pad.settings.language": "שפה:", "pad.importExport.import_export": "ייבוא/ייצוא", "pad.importExport.import": "העלאת כל קובץ טקסט או מסמך", diff --git a/src/locales/hr.json b/src/locales/hr.json index 186ad14454b..79404e42142 100644 --- a/src/locales/hr.json +++ b/src/locales/hr.json @@ -39,7 +39,6 @@ "pad.settings.linenocheck": "Brojevi redaka", "pad.settings.rtlcheck": "Želite li prikaz sadržaja s desna na lijevo?", "pad.settings.fontType": "Vrsta fonta:", - "pad.settings.globalView": "Globalni prikaz", "pad.settings.language": "Jezik:", "pad.importExport.import_export": "Uvoz/Izvoz", "pad.importExport.import": "Postavite bilo koju tekstualnu datoteku ili dokument", @@ -119,7 +118,7 @@ "pad.userlist.guest": "Gost", "pad.userlist.deny": "Odbij", "pad.userlist.approve": "Odobri", - "pad.editbar.clearcolors": "Ukloniti boje autorstva u cijelom blokiću?", + "pad.editbar.clearcolors": "Ukloniti boje autorstva u cijelom blokiću? Radnju nije moguće poništiti jednom kad je izvršena.", "pad.impexp.importbutton": "Uvezi odmah", "pad.impexp.importing": "Uvoženje...", "pad.impexp.confirmimport": "Uvoženje datoteke presnimit će trenutačni sadržaj blokića.\nJeste li sigurni da želite nastaviti?", diff --git a/src/locales/hrx.json b/src/locales/hrx.json index 74630efa5f4..73849a8369b 100644 --- a/src/locales/hrx.json +++ b/src/locales/hrx.json @@ -37,8 +37,6 @@ "pad.settings.rtlcheck": "Inhalt von rechts bis links lese?", "pad.settings.fontType": "Schriftoort:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Gemeinsame Oonsicht", "pad.settings.language": "Sproch:", "pad.importExport.import_export": "Import/Export", "pad.importExport.import": "Text-Datei orrer Dokument hochloode", diff --git a/src/locales/hsb.json b/src/locales/hsb.json index 798c596e62c..e5e86d468d4 100644 --- a/src/locales/hsb.json +++ b/src/locales/hsb.json @@ -39,8 +39,6 @@ "pad.settings.rtlcheck": "Wobsah wotprawa nalěwo čitać?", "pad.settings.fontType": "Pismowa družina:", "pad.settings.fontType.normal": "Normalny", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Globalny napohlad", "pad.settings.language": "Rěč:", "pad.importExport.import_export": "Import/Eksport", "pad.importExport.import": "Tekstowu dataju abo dokument nahrać", diff --git a/src/locales/hu.json b/src/locales/hu.json index fb00c6df2ed..ac9e7f30b9e 100644 --- a/src/locales/hu.json +++ b/src/locales/hu.json @@ -1,14 +1,14 @@ { "@metadata": { "authors": [ + "BanKris", + "Bencemac", + "Csega", "Dj", "Misibacsi", - "R-Joe", - "Tgr", - "Csega", - "BanKris", "Notramo", - "Bencemac" + "R-Joe", + "Tgr" ] }, "index.newPad": "Új notesz", @@ -46,8 +46,6 @@ "pad.settings.rtlcheck": "Tartalom olvasása balról jobbra?", "pad.settings.fontType": "Betűtípus:", "pad.settings.fontType.normal": "Szokásos", - "pad.settings.fontType.monospaced": "Írógépes", - "pad.settings.globalView": "Globális nézet", "pad.settings.language": "Nyelv:", "pad.importExport.import_export": "Import/export", "pad.importExport.import": "Tetszőleges szövegfájl vagy dokumentum feltöltése", diff --git a/src/locales/hy.json b/src/locales/hy.json index 20e0026cea3..7eaa58a48c3 100644 --- a/src/locales/hy.json +++ b/src/locales/hy.json @@ -19,7 +19,6 @@ "pad.settings.myView": "Իմ տեսարան", "pad.settings.rtlcheck": "Կարդալ բովանդակությունը աջից ձախ", "pad.settings.fontType": "Տառատեսակի տեսակը", - "pad.settings.globalView": "Ընդհանուր տեսքը", "pad.settings.language": "Լեզու", "pad.importExport.import_export": "Ներմուծում/արտահանում", "pad.importExport.import": "Բեռնել ցանկացած տեքստային ֆայլը կամ փաստաթուղթ", diff --git a/src/locales/ia.json b/src/locales/ia.json index 9a3fd31ec79..de8d1a16337 100644 --- a/src/locales/ia.json +++ b/src/locales/ia.json @@ -39,8 +39,6 @@ "pad.settings.rtlcheck": "Leger le contento de dextra a sinistra?", "pad.settings.fontType": "Typo de litteras:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospatial", - "pad.settings.globalView": "Vista global", "pad.settings.language": "Lingua:", "pad.importExport.import_export": "Importar/Exportar", "pad.importExport.import": "Incargar qualcunque file de texto o documento", @@ -118,7 +116,7 @@ "pad.userlist.guest": "Invitato", "pad.userlist.deny": "Refusar", "pad.userlist.approve": "Approbar", - "pad.editbar.clearcolors": "Rader le colores de autor in tote le documento?", + "pad.editbar.clearcolors": "Rader le colores de autor in tote le documento? Isto non pote esser disfacite", "pad.impexp.importbutton": "Importar ora", "pad.impexp.importing": "Importation in curso…", "pad.impexp.confirmimport": "Le importation de un file superscribera le texto actual del pad. Es tu secur de voler continuar?", diff --git a/src/locales/id.json b/src/locales/id.json index 220d204f704..738b5a3c3b0 100644 --- a/src/locales/id.json +++ b/src/locales/id.json @@ -40,7 +40,6 @@ "pad.settings.linenocheck": "Nomor baris", "pad.settings.rtlcheck": "Membaca dari kanan ke kiri?", "pad.settings.fontType": "Jenis fonta:", - "pad.settings.globalView": "Tampilan Global", "pad.settings.language": "Bahasa:", "pad.importExport.import_export": "Impor/Ekspor", "pad.importExport.import": "Unggah setiap berkas teks atau dokumen", diff --git a/src/locales/is.json b/src/locales/is.json index 87f52ac0dea..0d7fd5afa41 100644 --- a/src/locales/is.json +++ b/src/locales/is.json @@ -1,8 +1,8 @@ { "@metadata": { "authors": [ - "Sveinn í Felli", - "Sveinki" + "Sveinki", + "Sveinn í Felli" ] }, "index.newPad": "Ný skrifblokk", @@ -40,8 +40,6 @@ "pad.settings.rtlcheck": "Lesa innihaldið frá hægri til vinstri?", "pad.settings.fontType": "Leturgerð:", "pad.settings.fontType.normal": "Venjulegt", - "pad.settings.fontType.monospaced": "Jafnbreitt", - "pad.settings.globalView": "Yfirlitssýn", "pad.settings.language": "Tungumál:", "pad.importExport.import_export": "Flytja inn/út", "pad.importExport.import": "Settu inn hverskyns texta eða skjal", diff --git a/src/locales/it.json b/src/locales/it.json index 30881889d94..1552cab7a53 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -3,10 +3,10 @@ "authors": [ "Beta16", "Gianfranco", - "Muxator", - "Vituzzu", "Macofe", - "Nivit" + "Muxator", + "Nivit", + "Vituzzu" ] }, "index.newPad": "Nuovo Pad", @@ -44,8 +44,6 @@ "pad.settings.rtlcheck": "Leggere il contenuto da destra a sinistra?", "pad.settings.fontType": "Tipo di carattere:", "pad.settings.fontType.normal": "Normale", - "pad.settings.fontType.monospaced": "A larghezza fissa", - "pad.settings.globalView": "Visualizzazione globale", "pad.settings.language": "Lingua:", "pad.importExport.import_export": "Importazione/esportazione", "pad.importExport.import": "Carica un file di testo o un documento", @@ -125,7 +123,7 @@ "pad.userlist.guest": "Ospite", "pad.userlist.deny": "Nega", "pad.userlist.approve": "Approva", - "pad.editbar.clearcolors": "Eliminare i colori degli autori sull'intero documento?", + "pad.editbar.clearcolors": "Eliminare i colori degli autori sull'intero documento? Questa azione non può essere annullata", "pad.impexp.importbutton": "Importa ora", "pad.impexp.importing": "Importazione in corso...", "pad.impexp.confirmimport": "L'importazione del file sovrascriverà il testo attuale del Pad. Sei sicuro di voler procedere?", diff --git a/src/locales/ja.json b/src/locales/ja.json index 13d3d0c4a2f..be13d483764 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1,11 +1,11 @@ { "@metadata": { "authors": [ - "Shirayuki", - "Torinky", - "Omotecho", "Aefgh39622", - "Afaz" + "Afaz", + "Omotecho", + "Shirayuki", + "Torinky" ] }, "index.newPad": "新規作成", @@ -43,8 +43,6 @@ "pad.settings.rtlcheck": "右横書きにする", "pad.settings.fontType": "フォントの種類:", "pad.settings.fontType.normal": "通常", - "pad.settings.fontType.monospaced": "固定幅", - "pad.settings.globalView": "グローバル設定", "pad.settings.language": "言語:", "pad.importExport.import_export": "インポート/エクスポート", "pad.importExport.import": "あらゆるテキストファイルや文書をアップロードできます", diff --git a/src/locales/kab.json b/src/locales/kab.json index 191068ed814..ed9263a67fe 100644 --- a/src/locales/kab.json +++ b/src/locales/kab.json @@ -38,7 +38,6 @@ "pad.settings.linenocheck": "Uṭṭunen n izirigen", "pad.settings.rtlcheck": "Ɣeṛ agbur seg uyeffus s azelmaḍ?", "pad.settings.fontType": "Anaw n tsefsit:", - "pad.settings.globalView": "Timeẓri tamatut:", "pad.settings.language": "Tutlayt:", "pad.importExport.import_export": "Kter/Sifeḍ", "pad.importExport.import": "Sali aḍris neɣ isemli", diff --git a/src/locales/km.json b/src/locales/km.json index 4dea037aa50..5b45ac6f911 100644 --- a/src/locales/km.json +++ b/src/locales/km.json @@ -1,8 +1,8 @@ { "@metadata": { "authors": [ - "វ័ណថារិទ្ធ", - "Sovichet" + "Sovichet", + "វ័ណថារិទ្ធ" ] }, "index.newPad": "ផេតថ្មី", @@ -35,8 +35,6 @@ "pad.settings.rtlcheck": "អាន​ពី​ស្ដាំ​ទៅ​ឆ្វេង?", "pad.settings.fontType": "ប្រភេទពុម្ពអក្សរ៖", "pad.settings.fontType.normal": "ធម្មតា", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "គំហើញសកល", "pad.settings.language": "ភាសា៖", "pad.importExport.import_export": "នាំចូល/នាំចេញ", "pad.importExport.import": "ផ្ទុក​ឡើង​ឯកសារ​អត្ថបទ​ណាមួយ", diff --git a/src/locales/ko.json b/src/locales/ko.json index dc325cdd4f4..57c523c64f5 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -1,13 +1,13 @@ { "@metadata": { "authors": [ + "CYAN", "Hym411", - "아라", - "Revi", "Kurousagi", + "Revi", "SeoJeongHo", "Ykhwong", - "CYAN" + "아라" ] }, "index.newPad": "새 패드", @@ -45,8 +45,6 @@ "pad.settings.rtlcheck": "우횡서(오른쪽에서 왼쪽으로)입니까?", "pad.settings.fontType": "글꼴 종류:", "pad.settings.fontType.normal": "보통", - "pad.settings.fontType.monospaced": "고정 폭", - "pad.settings.globalView": "전역 보기", "pad.settings.language": "언어:", "pad.importExport.import_export": "가져오기/내보내기", "pad.importExport.import": "텍스트 파일이나 문서 올리기", @@ -126,7 +124,7 @@ "pad.userlist.guest": "손님", "pad.userlist.deny": "거부", "pad.userlist.approve": "승인", - "pad.editbar.clearcolors": "전체 문서의 저자 색을 지우시겠습니까?", + "pad.editbar.clearcolors": "전체 문서의 저자 색을 지우시겠습니까? 이 작업은 취소할 수 없습니다", "pad.impexp.importbutton": "지금 가져오기", "pad.impexp.importing": "가져오는 중...", "pad.impexp.confirmimport": "파일을 가져오면 패드의 현재 텍스트를 덮어쓰게 됩니다. 진행하시겠습니까?", diff --git a/src/locales/krc.json b/src/locales/krc.json index df04e94202a..11d3b6b44ad 100644 --- a/src/locales/krc.json +++ b/src/locales/krc.json @@ -8,8 +8,6 @@ "pad.colorpicker.save": "Сакъла", "pad.loading": "Джюклениу...", "pad.settings.fontType.normal": "Нормал", - "pad.settings.fontType.monospaced": "Монокенгликли", - "pad.settings.globalView": "Глобал кёрюнюу", "pad.settings.language": "Тил:", "pad.importExport.import_export": "Импорт/экспорт", "pad.importExport.importSuccessful": "Тыйыншлы!", diff --git a/src/locales/ksh.json b/src/locales/ksh.json index f6d0c3bb3a2..28ebf44ed16 100644 --- a/src/locales/ksh.json +++ b/src/locales/ksh.json @@ -39,8 +39,6 @@ "pad.settings.rtlcheck": "Schreff vun Rääschß noh Lenks?", "pad.settings.fontType": "Zoot Schreff", "pad.settings.fontType.normal": "Nommahl", - "pad.settings.fontType.monospaced": "einheidlesch brejde Zeische", - "pad.settings.globalView": "Et Ußsin för Alle", "pad.settings.language": "Schprohch:", "pad.importExport.import_export": "Empoot/Äxpoot", "pad.importExport.import": "Donn jeede Täx udder jeede Zoot Dokemänt huhlaade", diff --git a/src/locales/ku-latn.json b/src/locales/ku-latn.json index f80466036a1..abe1ea0169a 100644 --- a/src/locales/ku-latn.json +++ b/src/locales/ku-latn.json @@ -4,9 +4,9 @@ "Bikarhêner", "Dilyaramude", "George Animal", + "Ghybu", "Gomada", "Mehk63", - "Ghybu", "MikaelF" ] }, diff --git a/src/locales/lb.json b/src/locales/lb.json index c81ee018d85..9cda16bcac5 100644 --- a/src/locales/lb.json +++ b/src/locales/lb.json @@ -1,9 +1,9 @@ { "@metadata": { "authors": [ + "Gromper", "Robby", - "Soued031", - "Gromper" + "Soued031" ] }, "index.newPad": "Neie Pad", @@ -24,7 +24,7 @@ "pad.colorpicker.save": "Späicheren", "pad.colorpicker.cancel": "Ofbriechen", "pad.loading": "Lueden...", - "pad.noCookie": "Cookie gouf net fonnt. Erlaabt w.e.g. Cookien an Ärem Browser!", + "pad.noCookie": "Cookie gouf net fonnt. Erlaabt wgl. Cookien an Ärem Browser!", "pad.passwordRequired": "Dir braucht ee Passwuert fir dëse Pad opzemaachen", "pad.permissionDenied": "Dir hutt net déi néideg Rechter fir dëse Pad opzemaachen", "pad.wrongPassword": "Äert Passwuert ass falsch", @@ -33,7 +33,6 @@ "pad.settings.rtlcheck": "Inhalt vu riets no lénks liesen?", "pad.settings.fontType": "Schrëftart:", "pad.settings.fontType.normal": "Normal", - "pad.settings.globalView": "Global Vue", "pad.settings.language": "Sprooch:", "pad.importExport.import_export": "Import/Export", "pad.importExport.import": "Text-Fichier oder Dokument eroplueden", @@ -87,6 +86,6 @@ "pad.userlist.approve": "Zoustëmmen", "pad.impexp.importbutton": "Elo importéieren", "pad.impexp.importing": "Importéieren...", - "pad.impexp.uploadFailed": "D'Eroplueden huet net funktionéiert, probéiert w.e.g. nach eng Kéier", + "pad.impexp.uploadFailed": "D'Eroplueden huet net funktionéiert, probéiert wgl. nach eng Kéier", "pad.impexp.importfailed": "Den Import huet net funktionéiert" } diff --git a/src/locales/lki.json b/src/locales/lki.json index c8b8ecc9d5f..5559aca0787 100644 --- a/src/locales/lki.json +++ b/src/locales/lki.json @@ -1,8 +1,8 @@ { "@metadata": { "authors": [ - "Hosseinblue", "Arash71", + "Hosseinblue", "Lakzon" ] }, @@ -41,8 +41,6 @@ "pad.settings.rtlcheck": "خواندن نۆم جِک(محتوا)أژ لآ ڕاس بە چەپ؟", "pad.settings.fontType": ":شئؤۀ فؤنت", "pad.settings.fontType.normal": "عادی", - "pad.settings.fontType.monospaced": "پئنی-پهنا", - "pad.settings.globalView": "نمایش جەهانی", "pad.settings.language": ":زوون", "pad.importExport.import_export": "دەر بردن/إنۆم آووِردن", "pad.importExport.import": "بارنیائن هر جور نوشته یا سندئ", diff --git a/src/locales/lrc.json b/src/locales/lrc.json index 65429781094..104a9ba7b32 100644 --- a/src/locales/lrc.json +++ b/src/locales/lrc.json @@ -1,8 +1,8 @@ { "@metadata": { "authors": [ - "Mogoeilor", - "Lorestani" + "Lorestani", + "Mogoeilor" ] }, "index.newPad": "دٱفتٱرچٱ تازٱ", @@ -27,8 +27,6 @@ "pad.settings.linenocheck": "شمارٱ خٱتؽا", "pad.settings.fontType": "نوع فونت:", "pad.settings.fontType.normal": "عادی", - "pad.settings.fontType.monospaced": "تک جاگه", - "pad.settings.globalView": "دیئن جهونی", "pad.settings.language": "زڤون:", "pad.importExport.import_export": "ڤامین آوئردن/ڤ دٱر داٛئن", "pad.importExport.importSuccessful": "موئٱفٱق بی!", diff --git a/src/locales/lt.json b/src/locales/lt.json index 29b944598e1..21fc583ade0 100644 --- a/src/locales/lt.json +++ b/src/locales/lt.json @@ -2,11 +2,11 @@ "@metadata": { "authors": [ "Eitvys200", - "Mantak111", "I-svetaines", - "Zygimantus", + "Mantak111", + "Naktis", "Vogone", - "Naktis" + "Zygimantus" ] }, "index.newPad": "Naujas bloknotas", @@ -44,7 +44,6 @@ "pad.settings.rtlcheck": "Skaityti turinį iš dešinės į kairę?", "pad.settings.fontType": "Šrifto tipas:", "pad.settings.fontType.normal": "Normalus", - "pad.settings.globalView": "Bendras Vaizdas", "pad.settings.language": "Kalba:", "pad.importExport.import_export": "Importuoti/Eksportuoti", "pad.importExport.import": "Įkelkite bet kokį tekstinį failą arba dokumentą", diff --git a/src/locales/lv.json b/src/locales/lv.json index 7c0bc96cc23..5dd6a951149 100644 --- a/src/locales/lv.json +++ b/src/locales/lv.json @@ -3,10 +3,13 @@ "authors": [ "Admresdeserv.", "Jmg.cmdi", + "Oskars", "Papuass", "Silraks" ] }, + "index.newPad": "Tiek izmantots kā pogas teksts. Blociņš, Etherpad kontekstā, ir piezīmju blociņš, uz kura rakstīt.", + "index.createOpenPad": "vai izveidojiet/atveriet Blociņu ar nosaukumu:", "pad.toolbar.bold.title": "Treknrakstā (CTRL + B)", "pad.toolbar.italic.title": "Slīpraksta (Ctrl-es)", "pad.toolbar.underline.title": "Pasvītrojuma (CTRL + U)", @@ -19,6 +22,7 @@ "pad.toolbar.redo.title": "Atcelt atsaukšanu (CTRL + Y)", "pad.toolbar.clearAuthorship.title": "Notīrit autoru krāsas (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importēšanas/eksportēšanas no un uz citu failu formātiem", + "pad.toolbar.timeslider.title": "Laika-slidinātājs", "pad.toolbar.savedRevision.title": "Saglabāt pārskatīšanu", "pad.toolbar.settings.title": "Iestatījumi", "pad.toolbar.embed.title": "Koplietot un iegut šo pad", @@ -37,7 +41,6 @@ "pad.settings.rtlcheck": "Lasīt saturu no labās puses uz kreiso?", "pad.settings.fontType": "Fonta tips:", "pad.settings.fontType.normal": "Normāls", - "pad.settings.globalView": "Globālu skatījumu", "pad.settings.language": "Valoda:", "pad.importExport.import_export": "Importet/Eksportet", "pad.importExport.import": "Augšupielādēt jebkuru teksta failu vai dokumentu", diff --git a/src/locales/map-bms.json b/src/locales/map-bms.json index 8ebf70c7b8e..da02a51c018 100644 --- a/src/locales/map-bms.json +++ b/src/locales/map-bms.json @@ -1,8 +1,8 @@ { "@metadata": { "authors": [ - "StefanusRA", - "Empu" + "Empu", + "StefanusRA" ] }, "index.newPad": "Pad Anyar", @@ -38,8 +38,6 @@ "pad.settings.rtlcheck": "Waca isi sekang tengen maring kiwe?", "pad.settings.fontType": "Tipe Font:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Global View", "pad.settings.language": "Basa:", "pad.importExport.import_export": "Impor/Ekspor", "pad.importExport.import": "Unggahna berkas teks utawa dokumen", diff --git a/src/locales/mg.json b/src/locales/mg.json index 5279bdf328f..510db843330 100644 --- a/src/locales/mg.json +++ b/src/locales/mg.json @@ -27,7 +27,6 @@ "pad.settings.linenocheck": "Laharan'ny andalana", "pad.settings.rtlcheck": "Hamaky ny votoatiny miankavia?", "pad.settings.fontType": "Karazan-tarehintsoratra:", - "pad.settings.globalView": "Jery ankapobe", "pad.settings.language": "Fiteny:", "pad.importExport.import_export": "Hampiditra/Hamoaka", "pad.importExport.import": "Hampiditra raki-tsoratra na rakitra", diff --git a/src/locales/mk.json b/src/locales/mk.json index 0424e1abea2..0ea41bb2a33 100644 --- a/src/locales/mk.json +++ b/src/locales/mk.json @@ -41,8 +41,6 @@ "pad.settings.rtlcheck": "Содржините да се читаат од десно на лево?", "pad.settings.fontType": "Тип на фонт:", "pad.settings.fontType.normal": "Нормален", - "pad.settings.fontType.monospaced": "Непропорционален", - "pad.settings.globalView": "Општ поглед", "pad.settings.language": "Јазик:", "pad.importExport.import_export": "Увоз/Извоз", "pad.importExport.import": "Подигање на било каква текстуална податотека или документ", @@ -122,7 +120,7 @@ "pad.userlist.guest": "Гостин", "pad.userlist.deny": "Одбиј", "pad.userlist.approve": "Одобри", - "pad.editbar.clearcolors": "Да ги отстранам авторските бои од целиот документ?", + "pad.editbar.clearcolors": "Да ги отстранам авторските бои од целиот документ? Ова е неповратно", "pad.impexp.importbutton": "Увези сега", "pad.impexp.importing": "Увезувам...", "pad.impexp.confirmimport": "Увезувањето на податотека ќе го презапише тековниот текст на тетратката. Дали сте сигурни дека сакате да продолжите?", diff --git a/src/locales/ml.json b/src/locales/ml.json index c5a1e710336..8dfc9094b4a 100644 --- a/src/locales/ml.json +++ b/src/locales/ml.json @@ -1,15 +1,15 @@ { "@metadata": { "authors": [ + "Adithyak1997", "Akhilan", + "Ambadyanands", "Clockery", "Hrishikesh.kb", - "Praveenp", - "Santhosh.thottingal", - "Nesi", "Jinoytommanjaly", - "Ambadyanands", - "Adithyak1997" + "Nesi", + "Praveenp", + "Santhosh.thottingal" ] }, "index.newPad": "പുതിയ പാഡ്", @@ -47,8 +47,6 @@ "pad.settings.rtlcheck": "ഉള്ളടക്കം വലത്തുനിന്ന് ഇടത്തോട്ടാണോ വായിക്കേണ്ടത്?", "pad.settings.fontType": "ഫോണ്ട് തരം:", "pad.settings.fontType.normal": "സാധാരണം", - "pad.settings.fontType.monospaced": "മോണോസ്പേസ്", - "pad.settings.globalView": "മൊത്തക്കാഴ്ച", "pad.settings.language": "ഭാഷ:", "pad.importExport.import_export": "ഇറക്കുമതി/കയറ്റുമതി ചെയ്യുക", "pad.importExport.import": "എന്തെങ്കിലും എഴുത്തു പ്രമാണമോ രേഖയോ അപ്‌ലോഡ് ചെയ്യുക", diff --git a/src/locales/mn.json b/src/locales/mn.json index 6242d5915ad..24998c893c9 100644 --- a/src/locales/mn.json +++ b/src/locales/mn.json @@ -2,8 +2,8 @@ "@metadata": { "authors": [ "MongolWiki", - "Wisdom", - "Munkhzaya.E" + "Munkhzaya.E", + "Wisdom" ] }, "pad.toolbar.bold.title": "Болд тескт (Ctrl-B)", @@ -29,7 +29,6 @@ "pad.settings.linenocheck": "Мөрийн дугаар", "pad.settings.fontType": "Фонтын төрөл:", "pad.settings.fontType.normal": "Ердийн", - "pad.settings.fontType.monospaced": "Зай ихтэй фонт", "pad.settings.language": "Хэл:", "pad.importExport.import_export": "Импорт/Экспорт", "pad.importExport.import": "Бичвэр, текст файл оруулах", diff --git a/src/locales/ms.json b/src/locales/ms.json index e23fa30a676..3546f4ae504 100644 --- a/src/locales/ms.json +++ b/src/locales/ms.json @@ -40,8 +40,6 @@ "pad.settings.rtlcheck": "Membaca dari kanan ke kiri?", "pad.settings.fontType": "Jenis fon:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Paparan Sejagat", "pad.settings.language": "Bahasa:", "pad.importExport.import_export": "Import/Eksport", "pad.importExport.import": "Muat naik sebarang fail teks atau dokumen", diff --git a/src/locales/nap.json b/src/locales/nap.json index a5cec49864d..8e508b4c081 100644 --- a/src/locales/nap.json +++ b/src/locales/nap.json @@ -1,8 +1,8 @@ { "@metadata": { "authors": [ - "Chelin", "C.R.", + "Chelin", "Ruthven" ] }, @@ -40,8 +40,6 @@ "pad.settings.rtlcheck": "Lieggere 'e cuntenute 'a destra a smerza?", "pad.settings.fontType": "Tipo 'e funte:", "pad.settings.fontType.normal": "Nurmale", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Visualizzazione globbale", "pad.settings.language": "Llengua:", "pad.importExport.import_export": "Mpurtaziune/sportaziune", "pad.importExport.import": "Carreca coccherunto testo o documento", diff --git a/src/locales/nb.json b/src/locales/nb.json index e6450807516..95ce01417ec 100644 --- a/src/locales/nb.json +++ b/src/locales/nb.json @@ -1,11 +1,11 @@ { "@metadata": { "authors": [ - "Laaknor", - "Cocu", "Chameleon222", - "SuperPotato", - "Jon Harald Søby" + "Cocu", + "Jon Harald Søby", + "Laaknor", + "SuperPotato" ] }, "index.newPad": "Ny Pad", @@ -43,8 +43,6 @@ "pad.settings.rtlcheck": "Les innhold fra høyre til venstre?", "pad.settings.fontType": "Skrifttype:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Fast bredde", - "pad.settings.globalView": "Global visning", "pad.settings.language": "Språk:", "pad.importExport.import_export": "Importer/eksporter", "pad.importExport.import": "Last opp tekstfil eller dokument", diff --git a/src/locales/nds.json b/src/locales/nds.json index dfb92278228..7e302403338 100644 --- a/src/locales/nds.json +++ b/src/locales/nds.json @@ -38,8 +38,6 @@ "pad.settings.rtlcheck": "Lees Pad vun rechts nach links", "pad.settings.fontType": "Schriftoort:", "pad.settings.fontType.normal": "Normaal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Ansicht för all", "pad.settings.language": "Spraak:", "pad.importExport.import_export": "Rinhalen/Rutgeven", "pad.importExport.import": "Datei oder Dokument hoochladen", diff --git a/src/locales/ne.json b/src/locales/ne.json index 3e23659a5a6..cfbd279be1f 100644 --- a/src/locales/ne.json +++ b/src/locales/ne.json @@ -1,9 +1,10 @@ { "@metadata": { "authors": [ - "सरोज कुमार ढकाल", "Nirjal stha", - "राम प्रसाद जोशी" + "राम प्रसाद जोशी", + "सरोज कुमार ढकाल", + "हिमाल सुबेदी" ] }, "index.newPad": "नयाँ प्याड", @@ -26,7 +27,7 @@ "pad.toolbar.showusers.title": "यस प्याडमा रहेका प्रयोगकर्ता देखाउने", "pad.colorpicker.save": "सङ्ग्रह गर्ने", "pad.colorpicker.cancel": "रद्द", - "pad.loading": "लोड हुदैछ...", + "pad.loading": "खुल्दै छ…", "pad.passwordRequired": "यो प्यड खोल्न पासवर्ड चाहिन्छ", "pad.permissionDenied": "तपाईंलाई यो प्याड खोल्न अनुमति छैन", "pad.wrongPassword": "तपाईंको पासवर्ड गलत थियो", @@ -37,10 +38,8 @@ "pad.settings.colorcheck": "लेखकीय रङ्ग", "pad.settings.linenocheck": "हरफ संख्या", "pad.settings.rtlcheck": "के सामग्री दाहिने देखि देब्रे पढ्ने हो ?", - "pad.settings.fontType": "फन्ट प्रकार:", + "pad.settings.fontType": "लिपि प्रकार:", "pad.settings.fontType.normal": "सामान्य", - "pad.settings.fontType.monospaced": "मोनोस्पेस", - "pad.settings.globalView": "विश्वव्यापी दृष्य", "pad.settings.language": "भाषा:", "pad.importExport.import_export": "आयात/निर्यात", "pad.importExport.import": "कुनै पनि पाठ रहेको फाइल या कागजात अपलोड गर्नुहोस्", diff --git a/src/locales/nl.json b/src/locales/nl.json index 25dc0671483..f46fbbd843c 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -1,14 +1,16 @@ { "@metadata": { "authors": [ - "Siebrand", + "Klaas van Buiten", + "KlaasZ4usV", "Macofe", - "Robin0van0der0vliet", - "Robin van der Vliet", "Mainframe98", - "KlaasZ4usV", + "Marcelhospers", + "PonkoSasuke", "Rickvl", - "Marcelhospers" + "Robin van der Vliet", + "Robin0van0der0vliet", + "Siebrand" ] }, "index.newPad": "Nieuw pad", @@ -46,8 +48,6 @@ "pad.settings.rtlcheck": "Inhoud van rechts naar links lezen?", "pad.settings.fontType": "Lettertype:", "pad.settings.fontType.normal": "Normaal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Globaal overzicht", "pad.settings.language": "Taal:", "pad.importExport.import_export": "Importeren/exporteren", "pad.importExport.import": "Tekstbestand of document uploaden", @@ -127,7 +127,7 @@ "pad.userlist.guest": "Gast", "pad.userlist.deny": "Weigeren", "pad.userlist.approve": "Goedkeuren", - "pad.editbar.clearcolors": "Auteurskleuren voor het hele document wissen?", + "pad.editbar.clearcolors": "Auteurskleuren voor het hele document wissen? Dit kan je niet ongedaan maken", "pad.impexp.importbutton": "Nu importeren", "pad.impexp.importing": "Bezig met importeren…", "pad.impexp.confirmimport": "Door een bestand te importeren overschrijft u de huidige tekst van de pad. Wilt u echt doorgaan?", diff --git a/src/locales/nn.json b/src/locales/nn.json index dc6368ed935..2acbd46fe08 100644 --- a/src/locales/nn.json +++ b/src/locales/nn.json @@ -36,8 +36,6 @@ "pad.settings.linenocheck": "Linjenummer", "pad.settings.fontType": "Skrifttype:", "pad.settings.fontType.normal": "Vanleg", - "pad.settings.fontType.monospaced": "Fast breidd", - "pad.settings.globalView": "Global visning", "pad.settings.language": "Språk:", "pad.importExport.import_export": "Importer/eksporter", "pad.importExport.import": "Last opp tekstfiler eller dokument", diff --git a/src/locales/oc.json b/src/locales/oc.json index 5ec80904cd6..1c5a01207fa 100644 --- a/src/locales/oc.json +++ b/src/locales/oc.json @@ -1,7 +1,8 @@ { "@metadata": { "authors": [ - "Cedric31" + "Cedric31", + "Quentí" ] }, "index.newPad": "Pad novèl", @@ -39,8 +40,6 @@ "pad.settings.rtlcheck": "Lectura de dreita a esquèrra", "pad.settings.fontType": "Tipe de poliça :", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Vista d’ensemble", "pad.settings.language": "Lenga :", "pad.importExport.import_export": "Importar/Exportar", "pad.importExport.import": "Cargar un tèxte o un document", @@ -86,6 +85,8 @@ "pad.chat": "Chat", "pad.chat.title": "Dobrir lo chat associat a aqueste pad.", "pad.chat.loadmessages": "Cargar mai de messatges.", + "pad.chat.stick.title": "Ancorar la discussion a l’ecran", + "pad.chat.writeMessage.placeholder": "Escrivètz lo vòstre messatge aicí", "timeslider.pageTitle": "Istoric dinamic de {{appTitle}}", "timeslider.toolbar.returnbutton": "Retorn a aqueste Pad.", "timeslider.toolbar.authors": "Autors :", diff --git a/src/locales/olo.json b/src/locales/olo.json index e8db16f7f4f..331ddf87708 100644 --- a/src/locales/olo.json +++ b/src/locales/olo.json @@ -2,8 +2,8 @@ "@metadata": { "authors": [ "Denö", - "Mashoi7", - "Ilja.mos" + "Ilja.mos", + "Mashoi7" ] }, "pad.toolbar.underline.title": "Alleviivua (Ctrl+U)", diff --git a/src/locales/os.json b/src/locales/os.json index 941fe2b8e48..8d33b681068 100644 --- a/src/locales/os.json +++ b/src/locales/os.json @@ -37,8 +37,6 @@ "pad.settings.rtlcheck": "Мидис рахизӕй галиумӕ хъӕуы фӕрсын?", "pad.settings.fontType": "Шрифты хуыз:", "pad.settings.fontType.normal": "Хуымӕтӕг", - "pad.settings.fontType.monospaced": "Ӕмуӕрӕх", - "pad.settings.globalView": "Иууылы уынд", "pad.settings.language": "Æвзаг:", "pad.importExport.import_export": "Импорт/экспорт", "pad.importExport.import": "Исты текст файл кӕнӕ документ бавгӕнын", diff --git a/src/locales/pa.json b/src/locales/pa.json index 2b3a085af84..30661eb7c3a 100644 --- a/src/locales/pa.json +++ b/src/locales/pa.json @@ -3,9 +3,9 @@ "authors": [ "Aalam", "Babanwalia", - "ਪ੍ਰਚਾਰਕ", "Tow", - "ਗੁਰਪ੍ਰੀਤ ਹੁੰਦਲ" + "ਗੁਰਪ੍ਰੀਤ ਹੁੰਦਲ", + "ਪ੍ਰਚਾਰਕ" ] }, "index.newPad": "ਨਵਾਂ ਪੈਡ", @@ -43,8 +43,6 @@ "pad.settings.rtlcheck": "ਸਮੱਗਰੀ ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਪੜ੍ਹਨੀ ਹੈ?", "pad.settings.fontType": "ਫੋਂਟ ਕਿਸਮ:", "pad.settings.fontType.normal": "ਸਧਾਰਨ", - "pad.settings.fontType.monospaced": "ਮੋਨੋਸਪੇਸ", - "pad.settings.globalView": "ਗਲੋਬਲ ਝਲਕ", "pad.settings.language": "ਭਾਸ਼ਾ:", "pad.importExport.import_export": "ਇੰਪੋਰਟ/ਐਕਸਪੋਰਟ", "pad.importExport.import": "ਕੋਈ ਵੀ ਟੈਕਸਟ ਫਾਇਲ ਜਾਂ ਦਸਤਾਵੇਜ਼ ਅੱਪਲੋਡ ਕਰੋ", diff --git a/src/locales/pl.json b/src/locales/pl.json index e384241b3f4..7693bc0799e 100644 --- a/src/locales/pl.json +++ b/src/locales/pl.json @@ -1,15 +1,16 @@ { "@metadata": { "authors": [ - "Rezonansowy", - "Ty221", - "WTM", - "Woytecr", + "DeRudySoulStorm", "Macofe", - "Pan Cube", "Mateon1", + "Pan Cube", + "Rezonansowy", "Teeed", - "DeRudySoulStorm" + "Ty221", + "WTM", + "WaldiSt", + "Woytecr" ] }, "index.newPad": "Nowy dokument", @@ -47,8 +48,6 @@ "pad.settings.rtlcheck": "Czytasz treść od prawej do lewej?", "pad.settings.fontType": "Rodzaj czcionki:", "pad.settings.fontType.normal": "Normalna", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Widok ogólny", "pad.settings.language": "Język:", "pad.importExport.import_export": "Import/eksport", "pad.importExport.import": "Prześlij dowolny plik tekstowy lub dokument", @@ -94,6 +93,8 @@ "pad.chat": "Czat", "pad.chat.title": "Otwórz czat dla tego dokumentu.", "pad.chat.loadmessages": "Załaduj więcej wiadomości", + "pad.chat.stick.title": "Przyklej czat do ekranu", + "pad.chat.writeMessage.placeholder": "Napisz swoją wiadomość tutaj", "timeslider.pageTitle": "Oś czasu {{appTitle}}", "timeslider.toolbar.returnbutton": "Powróć do dokumentu", "timeslider.toolbar.authors": "Autorzy:", diff --git a/src/locales/pms.json b/src/locales/pms.json index 0ae18bf1e78..f1ec934f6e5 100644 --- a/src/locales/pms.json +++ b/src/locales/pms.json @@ -38,7 +38,6 @@ "pad.settings.linenocheck": "Nùmer ëd linia", "pad.settings.rtlcheck": "Ël contnù, dev-lo esse lesù da drita a snistra?", "pad.settings.fontType": "Sòrt ëd caràter:", - "pad.settings.globalView": "Vista d'ansem", "pad.settings.language": "Lenga:", "pad.importExport.import_export": "Amporté/Esporté", "pad.importExport.import": "Carié n'archivi o document ëd test", @@ -118,7 +117,7 @@ "pad.userlist.guest": "Anvità", "pad.userlist.deny": "Arfudé", "pad.userlist.approve": "Aprové", - "pad.editbar.clearcolors": "Dëscancelé ij color ëd paternità dj'autor an tut ël document?", + "pad.editbar.clearcolors": "Dëscancelé ij color ëd paternità dj'autor an tut ël document? Costa assion a peul nen esse anulà.", "pad.impexp.importbutton": "Amporté adess", "pad.impexp.importing": "An camin ch'as ampòrta...", "pad.impexp.confirmimport": "Amportand n'archivi as dëscancelërà ël test corent dël feuj. É-lo sigur ëd vorèj felo?", diff --git a/src/locales/ps.json b/src/locales/ps.json index 8db3a89e914..135e1354e57 100644 --- a/src/locales/ps.json +++ b/src/locales/ps.json @@ -30,8 +30,6 @@ "pad.settings.linenocheck": "د کرښو شمېرې", "pad.settings.fontType": "ليکبڼې ډول:", "pad.settings.fontType.normal": "نورمال", - "pad.settings.fontType.monospaced": "مونوسپېس", - "pad.settings.globalView": "نړېواله ښکارېدنه", "pad.settings.language": "ژبه:", "pad.importExport.importSuccessful": "بريالی شو!", "pad.importExport.exportetherpad": "اېترپډ", diff --git a/src/locales/pt-br.json b/src/locales/pt-br.json index 5f27927f8be..1394404aab0 100644 --- a/src/locales/pt-br.json +++ b/src/locales/pt-br.json @@ -1,22 +1,22 @@ { "@metadata": { "authors": [ + "Cainamarques", + "Dianakc", + "Eduardo Addad de Oliveira", + "Fasouzafreitas", "Gusta", + "Lpagliari", "Luckas", + "Macofe", "Prilopes", + "Rafaelff", + "Rodrigo codignoli", "TheGabrielZaum", "Titoncio", "Tuliouel", - "Rafaelff", - "Dianakc", - "Macofe", - "Rodrigo codignoli", - "Webysther", - "Fasouzafreitas", - "Lpagliari", "Walesson", - "Cainamarques", - "Eduardo Addad de Oliveira" + "Webysther" ] }, "index.newPad": "Nova Nota", @@ -54,8 +54,6 @@ "pad.settings.rtlcheck": "Ler conteúdo da direita para esquerda?", "pad.settings.fontType": "Tipo de fonte:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monoespaçada", - "pad.settings.globalView": "Visão global", "pad.settings.language": "Idioma:", "pad.importExport.import_export": "Importar/Exportar", "pad.importExport.import": "Enviar um arquivo texto ou documento", diff --git a/src/locales/pt.json b/src/locales/pt.json index ecd8da944ac..dea6c1d9a57 100644 --- a/src/locales/pt.json +++ b/src/locales/pt.json @@ -1,15 +1,15 @@ { "@metadata": { "authors": [ + "Athena in Wonderland", + "Cainamarques", "Hamilton Abreu", - "Luckas", - "Tuliouel", - "Waldir", "Imperadeiro98", + "Luckas", "Macofe", "Ti4goc", - "Cainamarques", - "Athena in Wonderland", + "Tuliouel", + "Waldir", "Waldyrious" ] }, @@ -48,8 +48,6 @@ "pad.settings.rtlcheck": "Ler o conteúdo da direita para a esquerda?", "pad.settings.fontType": "Tipo de letra:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monoespaçada", - "pad.settings.globalView": "Vista global", "pad.settings.language": "Língua:", "pad.importExport.import_export": "Importar/Exportar", "pad.importExport.import": "Carregar qualquer ficheiro de texto ou documento", diff --git a/src/locales/qqq.json b/src/locales/qqq.json index 512ef6a3103..5e290f0f875 100644 --- a/src/locales/qqq.json +++ b/src/locales/qqq.json @@ -41,8 +41,6 @@ "pad.settings.rtlcheck": "Used as label for checkbox for RTL (right-to-left) languages", "pad.settings.fontType": "Used as label for the \"Font type\" select box which has the following options:\n* {{msg-etherpadlite|Pad.settings.fontType.normal}}\n* {{msg-etherpadlite|Pad.settings.fontType.monospaced}}", "pad.settings.fontType.normal": "Used as an option in the \"Font type\" select box which is labeled {{msg-etherpadlite|Pad.settings.fontType}}.\n{{Identical|Normal}}", - "pad.settings.fontType.monospaced": "Used as an option in the \"Font type\" select box which is labeled {{msg-etherpadlite|Pad.settings.fontType}}.", - "pad.settings.globalView": "Section heading for global view settings, meaning the settings in this section will affect everyone viewing the pad.", "pad.settings.language": "This is a label for a select list of languages.\n{{Identical|Language}}", "pad.importExport.import_export": "Used as HTML

    heading of window.\n\nFollowed by the child heading {{msg-etherpadlite|Pad.importExport.import}}.", "pad.importExport.import": "Used as HTML

    heading.\n\nPreceded by the parent heading {{msg-etherpadlite|Pad.importExport.import_export}}.", @@ -113,7 +111,7 @@ "pad.userlist.guest": "Preceded by the link text which is labeled {{msg-etherpadlite|Pad.userlist.approve}}.\n{{Identical|Guest}}", "pad.userlist.deny": "Used as link text.\n\nFollowed by the link which is labeled {{msg-etherpadlite|Pad.userlist.approve}}.", "pad.userlist.approve": "Used as link text.\n\nPreceded by the link which is labeled {{msg-etherpadlite|Pad.userlist.deny}}.\n\nFollowed by the message {{msg-etherpadlite|Pad.userlist.guest}}.\n{{Identical|Approve}}", - "pad.editbar.clearcolors": "Used as confirmation message (JavaScript confirm() function).\n\nThis message means \"Are you sure you want to clear authorship colors on entire document?\".", + "pad.editbar.clearcolors": "Used as confirmation message (JavaScript confirm() function).\n\nThis message means \"Are you sure you want to clear authorship colors on entire document? This cannot be undone\".", "pad.impexp.importbutton": "Used as label for the Submit button.", "pad.impexp.importing": "Used to indicate that the file is being imported.\n{{Identical|Importing}}", "pad.impexp.confirmimport": "Used as confirmation message (JavaScript confirm() function).", diff --git a/src/locales/ro.json b/src/locales/ro.json index a73bfafc3de..91aecd15752 100644 --- a/src/locales/ro.json +++ b/src/locales/ro.json @@ -35,7 +35,6 @@ "pad.settings.colorcheck": "Culorile autorilor", "pad.settings.linenocheck": "Numere de linie", "pad.settings.fontType": "Tipul fontului:", - "pad.settings.globalView": "Vedere generală", "pad.settings.language": "Limbă:", "pad.importExport.import_export": "Import/Export", "pad.importExport.import": "Încarcă orice fișier text sau document", diff --git a/src/locales/ru.json b/src/locales/ru.json index c7b425cbb1a..49d0bcee98d 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -3,14 +3,14 @@ "authors": [ "Amire80", "DCamer", + "Diralik", "Eleferen", - "Okras", - "Volkov", - "Nzeemin", "Facenapalm", - "Patrick Star", "Movses", - "Diralik" + "Nzeemin", + "Okras", + "Patrick Star", + "Volkov" ] }, "index.newPad": "Создать", @@ -48,8 +48,6 @@ "pad.settings.rtlcheck": "Читать содержимое справа налево?", "pad.settings.fontType": "Тип шрифта:", "pad.settings.fontType.normal": "Обычный", - "pad.settings.fontType.monospaced": "Моноширинный", - "pad.settings.globalView": "Общий вид", "pad.settings.language": "Язык:", "pad.importExport.import_export": "Импорт/экспорт", "pad.importExport.import": "Загрузить любой текстовый файл или документ", diff --git a/src/locales/sco.json b/src/locales/sco.json index 274a85b488f..eaad6147f7c 100644 --- a/src/locales/sco.json +++ b/src/locales/sco.json @@ -1,8 +1,8 @@ { "@metadata": { "authors": [ - "John Reid", - "AmaryllisGardener" + "AmaryllisGardener", + "John Reid" ] }, "index.newPad": "New Pad", @@ -40,8 +40,6 @@ "pad.settings.rtlcheck": "Read content fae richt til cair?", "pad.settings.fontType": "Font type:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "The Global Luik", "pad.settings.language": "Leid:", "pad.importExport.import_export": "Import/Export", "pad.importExport.import": "Upload oni tex file or document", diff --git a/src/locales/sd.json b/src/locales/sd.json index 87ca2cb189c..3b159f01fc8 100644 --- a/src/locales/sd.json +++ b/src/locales/sd.json @@ -31,7 +31,6 @@ "pad.settings.linenocheck": "سٽ جا انگ", "pad.settings.rtlcheck": "مواد ساڄي کان کاٻي طرف پڙهندئو؟", "pad.settings.fontType": "اکرن جو قسم:", - "pad.settings.globalView": "عالمي نظارو", "pad.settings.language": "ٻولي:", "pad.importExport.import_export": "برآمد/درآمد", "pad.importExport.import": "ڪو به متن وارو فائيل يا دستاويز چاڙهيو", diff --git a/src/locales/sh.json b/src/locales/sh.json index f3dd2bbac1c..db60b3108f7 100644 --- a/src/locales/sh.json +++ b/src/locales/sh.json @@ -39,7 +39,6 @@ "pad.settings.linenocheck": "Brojevi redova", "pad.settings.rtlcheck": "Da prikažem sadržaj zdesna ulijevo?", "pad.settings.fontType": "Tip fonta:", - "pad.settings.globalView": "Globalni prikaz", "pad.settings.language": "Jezik:", "pad.importExport.import_export": "Uvoz/Izvoz", "pad.importExport.import": "Otpremanje bilo koje tekstualne datoteke ili dokumenta", diff --git a/src/locales/shn.json b/src/locales/shn.json index c5c81751949..67cf557b472 100644 --- a/src/locales/shn.json +++ b/src/locales/shn.json @@ -1,9 +1,9 @@ { "@metadata": { "authors": [ - "Saosukham", "Ninjastrikers", - "Saimawnkham" + "Saimawnkham", + "Saosukham" ] }, "index.newPad": "ၽႅတ်ႉမႂ်ႇ", @@ -40,7 +40,6 @@ "pad.settings.linenocheck": "တူဝ်လိၵ်ႈႁေႈႁၢႆး", "pad.settings.rtlcheck": "လူၵႂၢမ်းၼၢမ်း တႄႇၶႂႃတေႃႇသၢႆႉ", "pad.settings.fontType": "ၾွၼ်ႉတူဝ်လိၵ်ႈ", - "pad.settings.globalView": "ဝိဝ်းတင်းလူၵ်ႈ", "pad.settings.language": "ၽႃႇသႃႇၵႂၢမ်း:", "pad.importExport.import_export": "သူင်ႇၶဝ်/သူင်ႇဢွၵ်ႇ", "pad.importExport.import": "လူတ်ႇၶိုၼ်ႈ ၾၢႆႇလိၵ်ႈၵမ်ႈၽွင်ႈ ဢမ်ႇၼၼ် ပွင်ႈလိၵ်ႈ", diff --git a/src/locales/sk.json b/src/locales/sk.json index e199945a89c..67ac5ff31b0 100644 --- a/src/locales/sk.json +++ b/src/locales/sk.json @@ -1,11 +1,11 @@ { "@metadata": { "authors": [ - "Teslaton", "Kusavica", - "Rudko", + "Lexected", "Mark", - "Lexected" + "Rudko", + "Teslaton" ] }, "index.newPad": "Nový Pad", @@ -43,8 +43,6 @@ "pad.settings.rtlcheck": "Čítať obsah sprava doľava?", "pad.settings.fontType": "Typ písma:", "pad.settings.fontType.normal": "Normálne", - "pad.settings.fontType.monospaced": "Strojové", - "pad.settings.globalView": "Globálny pohľad", "pad.settings.language": "Jazyk:", "pad.importExport.import_export": "Import/Export", "pad.importExport.import": "Nahrať ľubovoľný textový súbor alebo dokument", diff --git a/src/locales/skr-arab.json b/src/locales/skr-arab.json index 2130b54315e..9941b6926e3 100644 --- a/src/locales/skr-arab.json +++ b/src/locales/skr-arab.json @@ -16,7 +16,6 @@ "pad.wrongPassword": "تہاݙ پاسورڈ غلط ہے", "pad.settings.padSettings": "پیڈ ترتیباں", "pad.settings.fontType": "فونٹ قسم:", - "pad.settings.globalView": "عالمی منظر", "pad.settings.language": "زبان:", "pad.importExport.importSuccessful": "کامیاب!", "pad.importExport.exportetherpad": "ایتھرپیڈ", diff --git a/src/locales/sl.json b/src/locales/sl.json index 37f716cd23e..7eb021e07af 100644 --- a/src/locales/sl.json +++ b/src/locales/sl.json @@ -2,9 +2,9 @@ "@metadata": { "authors": [ "Dbc334", + "HairyFotr", "Mateju", "Skalcaa", - "HairyFotr", "Upwinxp" ] }, @@ -43,8 +43,6 @@ "pad.settings.rtlcheck": "Ali naj se vsebina prebira od desne proti levi?", "pad.settings.fontType": "Vrsta pisave:", "pad.settings.fontType.normal": "Običajno", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Splošni pogled", "pad.settings.language": "Jezik:", "pad.importExport.import_export": "Uvoz/Izvoz", "pad.importExport.import": "Naloži katerokoli besedilno datoteko ali dokument.", diff --git a/src/locales/sq.json b/src/locales/sq.json index ad2dde8d896..0eb2c2bf4b6 100644 --- a/src/locales/sq.json +++ b/src/locales/sq.json @@ -41,8 +41,6 @@ "pad.settings.rtlcheck": "Të lexohet lënda nga e djathta në të majtë?", "pad.settings.fontType": "Lloj shkronjash:", "pad.settings.fontType.normal": "Normale", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Pamje e Përgjithshme", "pad.settings.language": "Gjuhë:", "pad.importExport.import_export": "Import/Eksport", "pad.importExport.import": "Ngarkoni cilëndo kartelë teksti ose dokument", diff --git a/src/locales/sr-ec.json b/src/locales/sr-ec.json index 15c553f551c..109668defae 100644 --- a/src/locales/sr-ec.json +++ b/src/locales/sr-ec.json @@ -1,13 +1,13 @@ { "@metadata": { "authors": [ + "Acamicamacaraca", "Aktron", + "BadDog", "Milicevic01", - "Милан Јелисавчић", - "Srdjan m", "Obsuser", - "Acamicamacaraca", - "BadDog" + "Srdjan m", + "Милан Јелисавчић" ] }, "index.newPad": "Нови Пад", @@ -45,8 +45,6 @@ "pad.settings.rtlcheck": "Читај садржај с десна на лево?", "pad.settings.fontType": "Врста фонта:", "pad.settings.fontType.normal": "Нормално", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Глобални приказ", "pad.settings.language": "Језик:", "pad.importExport.import_export": "Увоз/извоз", "pad.importExport.import": "Отпремите било коју текстуалну датотеку или документ", diff --git a/src/locales/sr-el.json b/src/locales/sr-el.json index 78771f07f55..3c4bff17ad0 100644 --- a/src/locales/sr-el.json +++ b/src/locales/sr-el.json @@ -1,5 +1,7 @@ { - "@metadata": [], + "@metadata": { + "authors": [] + }, "index.newPad": "Novi Pad", "index.createOpenPad": "ili napravite/otvorite pad sledećeg naziva:", "pad.toolbar.bold.title": "Podebljano (Ctrl+B)", @@ -35,8 +37,6 @@ "pad.settings.rtlcheck": "Čitaj sadržaj s desna na levo?", "pad.settings.fontType": "Vrsta fonta:", "pad.settings.fontType.normal": "Normalno", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Globalni prikaz", "pad.settings.language": "Jezik:", "pad.importExport.import_export": "Uvoz/izvoz", "pad.importExport.import": "Otpremite bilo koju tekstualnu datoteku ili dokument", diff --git a/src/locales/sv.json b/src/locales/sv.json index 7b03c12b272..69b086a164c 100644 --- a/src/locales/sv.json +++ b/src/locales/sv.json @@ -1,9 +1,9 @@ { "@metadata": { "authors": [ + "Jopparn", "Lokal Profil", - "WikiPhoenix", - "Jopparn" + "WikiPhoenix" ] }, "index.newPad": "Nytt block", @@ -41,8 +41,6 @@ "pad.settings.rtlcheck": "Vill du läsa innehållet från höger till vänster?", "pad.settings.fontType": "Typsnitt:", "pad.settings.fontType.normal": "Normal", - "pad.settings.fontType.monospaced": "Fast breddsteg", - "pad.settings.globalView": "Global vy", "pad.settings.language": "Språk:", "pad.importExport.import_export": "Importera/Exportera", "pad.importExport.import": "Ladda upp textfiler eller dokument", diff --git a/src/locales/ta.json b/src/locales/ta.json index c0a7cdc08a6..6f08c3bc6d0 100644 --- a/src/locales/ta.json +++ b/src/locales/ta.json @@ -29,7 +29,6 @@ "pad.settings.colorcheck": "ஆசிரியர் நிறங்கள்", "pad.settings.linenocheck": "வரி எண்கள்", "pad.settings.fontType": "எழுத்துரு வகை:", - "pad.settings.globalView": "உலக பார்வை", "pad.settings.language": "மொழி:", "pad.importExport.import_export": "இறக்குமதி/ஏற்றுமதி", "pad.importExport.importSuccessful": "வெற்றி!", diff --git a/src/locales/te.json b/src/locales/te.json index 13af39709aa..b34b93f2fa3 100644 --- a/src/locales/te.json +++ b/src/locales/te.json @@ -1,12 +1,12 @@ { "@metadata": { "authors": [ + "Chaduvari", "JVRKPRASAD", + "Kiranmayee", "Malkum", - "Veeven", - "Chaduvari", "Ravichandra", - "Kiranmayee" + "Veeven" ] }, "index.newPad": "కొత్త పలక", @@ -38,8 +38,6 @@ "pad.settings.linenocheck": "వరుస సంఖ్యలు", "pad.settings.fontType": "అక్షరశైలి రకం:", "pad.settings.fontType.normal": "సాధారణ", - "pad.settings.fontType.monospaced": "మోనోస్పేస్", - "pad.settings.globalView": "బయటకి దర్శనం", "pad.settings.language": "భాష", "pad.importExport.import_export": "దిగుమతి/ఎగుమతి", "pad.importExport.import": "పాఠము దస్త్రము లేదా పత్రమును దిగుమతి చేయుము", diff --git a/src/locales/th.json b/src/locales/th.json index d5c24374b34..60030ec3315 100644 --- a/src/locales/th.json +++ b/src/locales/th.json @@ -38,7 +38,6 @@ "pad.settings.linenocheck": "เลขบรรทัด", "pad.settings.rtlcheck": "อ่านเนื้อหาจากขวาไปซ้ายหรือไม่?", "pad.settings.fontType": "ชนิดแบบอักษร:", - "pad.settings.globalView": "มุมมองสากล", "pad.settings.language": "ภาษา:", "pad.importExport.import_export": "นำเข้า/ส่งออก", "pad.importExport.import": "อัปโหลดไฟล์ข้อความหรือเอกสารใดๆ", diff --git a/src/locales/tr.json b/src/locales/tr.json index 1358bdeda1f..b27aa3d288f 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -1,31 +1,32 @@ { "@metadata": { "authors": [ + "BaRaN6161 TURK", "Emperyan", "Erdemaslancan", + "Grkn gll", + "Hedda", "Joseph", + "McAang", "Meelo", "Trockya", - "McAang", - "Vito Genovese", - "Hedda", - "Grkn gll" + "Vito Genovese" ] }, "index.newPad": "Yeni Bloknot", - "index.createOpenPad": "ya da şu isimle bir Bloknot oluştur/aç:", - "pad.toolbar.bold.title": "Kalın (Ctrl-B)", - "pad.toolbar.italic.title": "Eğik (Ctrl-I)", - "pad.toolbar.underline.title": "Altı Çizili (Ctrl-U)", + "index.createOpenPad": "veya şu adla bir Bloknot oluşturun/açın:", + "pad.toolbar.bold.title": "Kalın (Ctrl+B)", + "pad.toolbar.italic.title": "Eğik (Ctrl+I)", + "pad.toolbar.underline.title": "Altı Çizili (Ctrl+U)", "pad.toolbar.strikethrough.title": "Üstü Çizili (Ctrl+5)", "pad.toolbar.ol.title": "Sıralı liste (Ctrl+Shift+N)", "pad.toolbar.ul.title": "Sırasız Liste (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Girintiyi arttır (TAB)", "pad.toolbar.unindent.title": "Girintiyi azalt (Shift+TAB)", - "pad.toolbar.undo.title": "Geri Al (Ctrl-Z)", + "pad.toolbar.undo.title": "Geri Al (Ctrl+Z)", "pad.toolbar.redo.title": "Yinele (Ctrl+Y)", "pad.toolbar.clearAuthorship.title": "Yazarlık Renklerini Temizle (Ctrl+Shift+C)", - "pad.toolbar.import_export.title": "Farklı dosya biçimlerini içeri/dışarı aktar", + "pad.toolbar.import_export.title": "Farklı dosya biçimlerini içe/dışa aktar", "pad.toolbar.timeslider.title": "Zaman Çizelgesi", "pad.toolbar.savedRevision.title": "Düzeltmeyi Kaydet", "pad.toolbar.settings.title": "Ayarlar", @@ -47,13 +48,11 @@ "pad.settings.rtlcheck": "İçerik sağdan sola doğru okunsun mu?", "pad.settings.fontType": "Yazı tipi:", "pad.settings.fontType.normal": "Olağan", - "pad.settings.fontType.monospaced": "Tek aralıklı", - "pad.settings.globalView": "Genel Görünüm", "pad.settings.language": "Dil:", - "pad.importExport.import_export": "İçeri aktar/Dışarı aktar", + "pad.importExport.import_export": "İçe/Dışa aktar", "pad.importExport.import": "Herhangi bir metin dosyası ya da belgesi yükle", "pad.importExport.importSuccessful": "Başarılı!", - "pad.importExport.export": "Mevcut bloknotu şu olarak dışa aktar:", + "pad.importExport.export": "Mevcut bloknotu şuraya dışa aktar:", "pad.importExport.exportetherpad": "Etherpad", "pad.importExport.exporthtml": "HTML", "pad.importExport.exportplain": "Düz metin", @@ -79,16 +78,16 @@ "pad.modals.slowcommit.explanation": "Sunucu yanıt vermiyor.", "pad.modals.slowcommit.cause": "Bu hata ağ bağlantısı sebebiyle olabilir.", "pad.modals.badChangeset.explanation": "Yaptığınız bir düzenleme eşitleme sunucusu tarafından kullanışsız/kural dışı olarak sınıflandırıldı.", - "pad.modals.badChangeset.cause": "Bu, yanlış sunucu yapılandırması ya da başka bir beklenmedik davranışlar sonucunda olmuş olabilir. Bu size bir hataymış gibi geliyorsa lütfen servis yöneticisiyle iletişime geçin. Düzenlemeye devam etmek için yeniden bağlanmayı deneyin.", + "pad.modals.badChangeset.cause": "Bunun nedeni, yanlış bir sunucu yapılandırması veya beklenmeyen başka bir davranış olabilir. Bunun bir hata olduğunu düşünüyorsanız lütfen servis yöneticisine başvurun. Düzenlemeye devam etmek için yeniden bağlanmayı deneyin.", "pad.modals.corruptPad.explanation": "Erişmeye çalıştığınız bloknot bozuk.", - "pad.modals.corruptPad.cause": "Bu, yanlış sunucu yapılandırması ya da başka bir beklenmedik davranışlardan kaynaklanabilir. Lütfen servis yöneticisiyle iletişime geçin.", + "pad.modals.corruptPad.cause": "Bunun nedeni yanlış bir sunucu yapılandırması veya beklenmeyen başka bir davranış olabilir. Lütfen servis yöneticisine başvurun.", "pad.modals.deleted": "Silindi.", "pad.modals.deleted.explanation": "Bu bloknot kaldırılmış.", "pad.modals.disconnected": "Bağlantınız koptu.", "pad.modals.disconnected.explanation": "Sunucu bağlantısı kaybedildi", "pad.modals.disconnected.cause": "Sunucu kullanılamıyor olabilir. Bunun devam etmesi durumunda servis yöneticisine bildirin.", "pad.share": "Bu bloknotu paylaş", - "pad.share.readonly": "Salt okunur", + "pad.share.readonly": "Sadece oku", "pad.share.link": "Bağlantı", "pad.share.emebdcode": "URL'yi göm", "pad.chat": "Sohbet", @@ -128,12 +127,12 @@ "pad.userlist.guest": "Misafir", "pad.userlist.deny": "Reddet", "pad.userlist.approve": "Onayla", - "pad.editbar.clearcolors": "Bütün belgedeki yazarlık renkleri silinsin mi?", + "pad.editbar.clearcolors": "Bütün belgedeki yazarlık renkleri silinsin mi? Bu işlem geri alınamaz", "pad.impexp.importbutton": "Şimdi İçe Aktar", "pad.impexp.importing": "İçe aktarıyor...", "pad.impexp.confirmimport": "Bir dosya içe aktarılırken bloknotun mevcut metninin üzerine yazdırılır. Devam etmek istediğinizden emin misiniz?", "pad.impexp.convertFailed": "Bu dosyayı içe aktarmak mümkün değil. Lütfen farklı bir belge biçimi kullanın ya da elle kopyala yapıştır yapın", - "pad.impexp.padHasData": "Biz bu dosyayı içe aktaramadık çünkü bu Bloknot zaten değiştirilmiş, lütfen yeni bir bloknot içe aktarın.", + "pad.impexp.padHasData": "Bu Pad'in zaten değişiklikleri olduğu için bu dosyayı içe aktaramadık, lütfen yeni bir bloknota aktarın", "pad.impexp.uploadFailed": "Yükleme başarısız, lütfen tekrar deneyin", "pad.impexp.importfailed": "İçe aktarım başarısız oldu", "pad.impexp.copypaste": "Lütfen kopyala yapıştır yapın", diff --git a/src/locales/uk.json b/src/locales/uk.json index 9a6ab8e71fe..968920d24f7 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -3,14 +3,14 @@ "authors": [ "Andriykopanytsia", "Base", + "Bunyk", + "Lxlalexlxl", + "Movses", "Olvin", + "Piramidion", "Steve.rusyn", "SteveR", - "Lxlalexlxl", - "Григорій Пугач", - "Bunyk", - "Piramidion", - "Movses" + "Григорій Пугач" ] }, "index.newPad": "Створити", @@ -48,8 +48,6 @@ "pad.settings.rtlcheck": "Читати вміст з права на ліво?", "pad.settings.fontType": "Тип шрифту:", "pad.settings.fontType.normal": "Звичайний", - "pad.settings.fontType.monospaced": "Моноширинний", - "pad.settings.globalView": "Загальний вигляд", "pad.settings.language": "Мова:", "pad.importExport.import_export": "Імпорт/Експорт", "pad.importExport.import": "Завантажити будь-який текстовий файл або документ", @@ -129,7 +127,7 @@ "pad.userlist.guest": "Гість", "pad.userlist.deny": "Заборонити", "pad.userlist.approve": "Підтвердити", - "pad.editbar.clearcolors": "Очистити кольори у всьому документі?", + "pad.editbar.clearcolors": "Очистити кольори у всьому документі? Це не можна буде відкотити", "pad.impexp.importbutton": "Імпортувати зараз", "pad.impexp.importing": "Імпорт...", "pad.impexp.confirmimport": "Імпортування файлу перезапише поточний текст документа. Ви дійсно хочете продовжити?", diff --git a/src/locales/vec.json b/src/locales/vec.json new file mode 100644 index 00000000000..375390d7df0 --- /dev/null +++ b/src/locales/vec.json @@ -0,0 +1,42 @@ +{ + "@metadata": { + "authors": [ + "Fierodelveneto" + ] + }, + "index.newPad": "Novo Pad", + "index.createOpenPad": "O creare o verxare on Pad co'l nome:", + "pad.toolbar.bold.title": "Groseto (Ctrl-B)", + "pad.toolbar.italic.title": "Corsivo (Ctrl-I)", + "pad.toolbar.underline.title": "Sotolineà (Ctrl-U)", + "pad.toolbar.strikethrough.title": "Barà (Ctrl+5)", + "pad.toolbar.ol.title": "Ełenco numarà (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Ełenco pontà (Ctrl+Shift+L)", + "pad.toolbar.indent.title": "Indentasion (TAB)", + "pad.toolbar.unindent.title": "Scursa indentasion (Shift+TAB)", + "pad.toolbar.undo.title": "Dasa stare (Ctrl-Z)", + "pad.toolbar.redo.title": "Ripeti (Ctrl-Y)", + "pad.toolbar.clearAuthorship.title": "Cava i cołori che i indega i autori (Ctrl+Shift+C)", + "pad.toolbar.import_export.title": "Inporta/esporta da/a fidarenti formati de file", + "pad.toolbar.timeslider.title": "Prexentasion storego", + "pad.toolbar.savedRevision.title": "Version salvada", + "pad.toolbar.settings.title": "Inpostasion", + "pad.toolbar.embed.title": "Spartisi e incorpora sto Pad", + "pad.toolbar.showusers.title": "Varda i utenti so sto Pad", + "pad.colorpicker.save": "Salva", + "pad.colorpicker.cancel": "Descançełare", + "pad.loading": "Drio cargar...", + "pad.noCookie": "El cookie no el xé sta catà. Cosenti i cookie n'tel to navegadore web.", + "timeslider.month.january": "Xenaro", + "timeslider.month.march": "Marso", + "timeslider.month.april": "Apriłe", + "timeslider.month.may": "Majo", + "timeslider.month.june": "Xugno", + "timeslider.month.july": "Lujo", + "timeslider.month.august": "Agosto", + "timeslider.month.september": "Setenbre", + "timeslider.month.october": "Otobre", + "timeslider.month.november": "Novenbre", + "timeslider.month.december": "Disenbre", + "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autore, other: autori ]} sensa nome" +} diff --git a/src/locales/vi.json b/src/locales/vi.json index 57f58e0cbde..42bc84806f6 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -2,9 +2,9 @@ "@metadata": { "authors": [ "Baonguyen21022003", + "Max20091", "Minh Nguyen", - "Tuankiet65", - "Max20091" + "Tuankiet65" ] }, "index.newPad": "Tạo một Pad mới", @@ -40,8 +40,6 @@ "pad.settings.rtlcheck": "Đọc nội dung từ phải sang trái?", "pad.settings.fontType": "Kiểu phông chữ:", "pad.settings.fontType.normal": "Thường", - "pad.settings.fontType.monospaced": "Monospace", - "pad.settings.globalView": "Toàn cầu", "pad.settings.language": "Ngôn ngữ:", "pad.importExport.import_export": "Xuất/Nhập", "pad.importExport.import": "Tải lên bất kỳ tập tin văn bản hoặc tài liệu", diff --git a/src/locales/zh-hans.json b/src/locales/zh-hans.json index 1d456ff7602..7c0cd2d70bc 100644 --- a/src/locales/zh-hans.json +++ b/src/locales/zh-hans.json @@ -1,19 +1,19 @@ { "@metadata": { "authors": [ + "94rain", "Dimension", "Hydra", "Hzy980512", + "JuneAugust", "Liuxinyu970226", "Qiyue2001", "Shangkuanlc", "Shizhao", + "VulpesVulpes825", "Yfdyh000", "乌拉跨氪", - "燃玉", - "JuneAugust", - "94rain", - "VulpesVulpes825" + "燃玉" ] }, "index.newPad": "新记事本", @@ -51,8 +51,6 @@ "pad.settings.rtlcheck": "从右到左阅读内容吗?", "pad.settings.fontType": "字体类型:", "pad.settings.fontType.normal": "正常", - "pad.settings.fontType.monospaced": "等宽字体", - "pad.settings.globalView": "所有人视窗", "pad.settings.language": "语言:", "pad.importExport.import_export": "导入/导出", "pad.importExport.import": "上载任何文本文件或档案", diff --git a/src/locales/zh-hant.json b/src/locales/zh-hant.json index 6d43f67d7a1..438e6475aad 100644 --- a/src/locales/zh-hant.json +++ b/src/locales/zh-hant.json @@ -2,52 +2,51 @@ "@metadata": { "authors": [ "Justincheng12345", + "Kly", + "LNDDYL", "Liuxinyu970226", + "Pan93412", "Shangkuanlc", "Shirayuki", "Simon Shek", - "LNDDYL", - "Wehwei", - "Kly" + "Wehwei" ] }, "index.newPad": "新記事本", - "index.createOpenPad": "或創建/開啟以下名稱的記事本:", - "pad.toolbar.bold.title": "粗體(Ctrl-B)", - "pad.toolbar.italic.title": "斜體(Ctrl-I)", - "pad.toolbar.underline.title": "底線(Ctrl-U)", + "index.createOpenPad": "或建立/開啟以下名稱的記事本:", + "pad.toolbar.bold.title": "粗體(Ctrl+B)", + "pad.toolbar.italic.title": "斜體(Ctrl+I)", + "pad.toolbar.underline.title": "底線(Ctrl+U)", "pad.toolbar.strikethrough.title": "刪除線(Ctrl+5)", "pad.toolbar.ol.title": "有序清單(Ctrl+Shift+N)", "pad.toolbar.ul.title": "無序清單(Ctrl+Shift+L)", "pad.toolbar.indent.title": "縮排(TAB)", "pad.toolbar.unindent.title": "凸排(Shift+TAB)", - "pad.toolbar.undo.title": "撤銷(Ctrl-Z)", + "pad.toolbar.undo.title": "復原(Ctrl+Z)", "pad.toolbar.redo.title": "重做 (Ctrl+Y)", "pad.toolbar.clearAuthorship.title": "清除協作者顏色區別 (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "以其他檔案格式匯入/匯出", "pad.toolbar.timeslider.title": "時間軸", - "pad.toolbar.savedRevision.title": "儲存修訂", + "pad.toolbar.savedRevision.title": "儲存修訂版", "pad.toolbar.settings.title": "設定", "pad.toolbar.embed.title": "分享和嵌入此記事本", "pad.toolbar.showusers.title": "顯示此記事本的使用者", "pad.colorpicker.save": "儲存", "pad.colorpicker.cancel": "取消", "pad.loading": "載入中...", - "pad.noCookie": "找不到 Cookie。請讓你的瀏覽器允許 Cookie!", - "pad.passwordRequired": "您需要密碼才能訪問這個記事本", - "pad.permissionDenied": "你沒有訪問這個記事本的權限", + "pad.noCookie": "找不到 Cookie。請允許瀏覽器使用 Cookie!", + "pad.passwordRequired": "您需要密碼才能存取這個記事本", + "pad.permissionDenied": "你沒有存取這個記事本的權限", "pad.wrongPassword": "密碼錯誤", "pad.settings.padSettings": "記事本設定", "pad.settings.myView": "我的視窗", - "pad.settings.stickychat": "永遠在屏幕上顯示聊天", + "pad.settings.stickychat": "永遠在螢幕上顯示聊天", "pad.settings.chatandusers": "顯示聊天與使用者", "pad.settings.colorcheck": "協作者顏色", "pad.settings.linenocheck": "行號", "pad.settings.rtlcheck": "從右至左讀取內容?", - "pad.settings.fontType": "字體類型:", + "pad.settings.fontType": "字型類型:", "pad.settings.fontType.normal": "正常", - "pad.settings.fontType.monospaced": "等寬", - "pad.settings.globalView": "所有人的視窗", "pad.settings.language": "語言:", "pad.importExport.import_export": "匯入/匯出", "pad.importExport.import": "上載任何文字檔或文件", @@ -59,21 +58,21 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF(開放文件格式)", - "pad.importExport.abiword.innerHTML": "您只可以純文字或 HTML 格式檔匯入。安裝\n AbiWord 取得更多進階的匯入功能。", + "pad.importExport.abiword.innerHTML": "您只可以從純文字或 HTML 格式檔匯入。安裝\n AbiWord 以取得更多進階的匯入功能。", "pad.modals.connected": "已連線。", - "pad.modals.reconnecting": "重新連接到您的記事本...", + "pad.modals.reconnecting": "重新連線到您的記事本…", "pad.modals.forcereconnect": "強制重新連線", - "pad.modals.reconnecttimer": "嘗試重新連接在", + "pad.modals.reconnecttimer": "下一次重新連線會在", "pad.modals.cancel": "取消", "pad.modals.userdup": "在另一個視窗中開啟", "pad.modals.userdup.explanation": "此記事本似乎在此電腦上的多個瀏覽器視窗中開啟。", - "pad.modals.userdup.advice": "重新連接到此視窗。", + "pad.modals.userdup.advice": "重新連線,並改用這個視窗。", "pad.modals.unauth": "未授權", - "pad.modals.unauth.explanation": "您的權限在查看此頁時發生更改。請嘗試重新連接。", - "pad.modals.looping.explanation": "與同步伺服器間有通信問題。", - "pad.modals.looping.cause": "也許您是通過不相容的防火牆或代理伺服器連線。", - "pad.modals.initsocketfail": "無法訪問伺服器。", - "pad.modals.initsocketfail.explanation": "無法連接到同步伺服器。", + "pad.modals.unauth.explanation": "您的權限在變更此頁時變更了。請嘗試重新連線。", + "pad.modals.looping.explanation": "與同步伺服器間有通訊問題。", + "pad.modals.looping.cause": "也許您是透過不相容的防火牆或代理伺服器連線。", + "pad.modals.initsocketfail": "無法存取伺服器。", + "pad.modals.initsocketfail.explanation": "無法連線到同步伺服器。", "pad.modals.initsocketfail.cause": "這可能是因為瀏覽器或網際網路連線問題所造成。", "pad.modals.slowcommit.explanation": "伺服器沒有回應。", "pad.modals.slowcommit.cause": "這可能是因為網路連線問題所造成。", @@ -127,7 +126,7 @@ "pad.userlist.guest": "訪客", "pad.userlist.deny": "拒絕", "pad.userlist.approve": "批准", - "pad.editbar.clearcolors": "清除整個文檔的協作者顏色區別嗎?", + "pad.editbar.clearcolors": "清除整個文檔的協作者顏色區別嗎?此操作無法還原", "pad.impexp.importbutton": "現在匯入", "pad.impexp.importing": "匯入中...", "pad.impexp.confirmimport": "匯入的檔案將會覆蓋記事本內目前的文字。您確定要繼續嗎?", diff --git a/src/node/db/API.js b/src/node/db/API.js index 998d9acd1d5..71bd09eca3f 100644 --- a/src/node/db/API.js +++ b/src/node/db/API.js @@ -837,6 +837,34 @@ exports.createDiffHTML = async function(padID, startRev, endRev) { return { html, authors }; } +/**********************/ +/** GLOBAL FUNCTIONS **/ +/**********************/ + +/** + getStats() returns an json object with some instance stats + + Example returns: + + {"code":0,"message":"ok","data":{"totalPads":3,"totalSessions": 2,"totalActivePads": 1}} + {"code":4,"message":"no or wrong API Key","data":null} + */ + +exports.getStats = async function() { + const sessionInfos = padMessageHandler.sessioninfos; + + const sessionKeys = Object.keys(sessionInfos); + const activePads = new Set(Object.entries(sessionInfos).map(k => k[1].padId)); + + const { padIDs } = await padManager.listAllPads(); + + return { + totalPads: padIDs.length, + totalSessions: sessionKeys.length, + totalActivePads: activePads.size, + } +} + /******************************/ /** INTERNAL HELPER FUNCTIONS */ /******************************/ diff --git a/src/node/db/DB.js b/src/node/db/DB.js index 57356366582..4150743debb 100644 --- a/src/node/db/DB.js +++ b/src/node/db/DB.js @@ -45,29 +45,29 @@ exports.init = function() { console.error("ERROR: Problem while initalizing the database"); console.error(err.stack ? err.stack : err); process.exit(1); - } else { - // everything ok, set up Promise-based methods - ['get', 'set', 'findKeys', 'getSub', 'setSub', 'remove', 'doShutdown'].forEach(fn => { - exports[fn] = util.promisify(db[fn].bind(db)); - }); + } - // set up wrappers for get and getSub that can't return "undefined" - let get = exports.get; - exports.get = async function(key) { - let result = await get(key); - return (result === undefined) ? null : result; - }; + // everything ok, set up Promise-based methods + ['get', 'set', 'findKeys', 'getSub', 'setSub', 'remove', 'doShutdown'].forEach(fn => { + exports[fn] = util.promisify(db[fn].bind(db)); + }); - let getSub = exports.getSub; - exports.getSub = async function(key, sub) { - let result = await getSub(key, sub); - return (result === undefined) ? null : result; - }; + // set up wrappers for get and getSub that can't return "undefined" + let get = exports.get; + exports.get = async function(key) { + let result = await get(key); + return (result === undefined) ? null : result; + }; - // exposed for those callers that need the underlying raw API - exports.db = db; - resolve(); - } + let getSub = exports.getSub; + exports.getSub = async function(key, sub) { + let result = await getSub(key, sub); + return (result === undefined) ? null : result; + }; + + // exposed for those callers that need the underlying raw API + exports.db = db; + resolve(); }); }); } diff --git a/src/node/db/Pad.js b/src/node/db/Pad.js index cf016444cec..158bfafb57c 100644 --- a/src/node/db/Pad.js +++ b/src/node/db/Pad.js @@ -16,6 +16,7 @@ var readOnlyManager = require("./ReadOnlyManager"); var crypto = require("crypto"); var randomString = require("../utils/randomstring"); var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks'); +var promises = require('../utils/promises') // serialization/deserialization attributes var attributeBlackList = ["id"]; @@ -482,14 +483,14 @@ Pad.prototype.remove = async function remove() { db.remove("readonly2pad:" + readonlyID); // delete all chat messages - for (let i = 0, n = this.chatHead; i <= n; ++i) { - db.remove("pad:" + padID + ":chat:" + i); - } + promises.timesLimit(this.chatHead + 1, 500, function (i) { + return db.remove("pad:" + padID + ":chat:" + i, null); + }) // delete all revisions - for (let i = 0, n = this.head; i <= n; ++i) { - db.remove("pad:" + padID + ":revs:" + i); - } + promises.timesLimit(this.head + 1, 500, function (i) { + return db.remove("pad:" + padID + ":revs:" + i, null); + }) // remove pad from all authors who contributed this.getAllAuthors().forEach(authorID => { diff --git a/src/node/db/PadManager.js b/src/node/db/PadManager.js index 23164a7a961..89e6a84ab90 100644 --- a/src/node/db/PadManager.js +++ b/src/node/db/PadManager.js @@ -49,8 +49,8 @@ var globalPads = { * Updated without db access as new pads are created/old ones removed. */ let padList = { - list: [], - sorted : false, + list: new Set(), + cachedList: undefined, initiated: false, init: async function() { let dbData = await db.findKeys("pad:*", "*:*:*"); @@ -59,7 +59,7 @@ let padList = { this.initiated = true; for (let val of dbData) { - this.addPad(val.replace(/pad:/,""), false); + this.addPad(val.replace(/^pad:/,""), false); } } @@ -78,29 +78,26 @@ let padList = { getPads: async function() { await this.load(); - if (!this.sorted) { - this.list.sort(); - this.sorted = true; + if (!this.cachedList) { + this.cachedList = Array.from(this.list).sort(); } - return this.list; + return this.cachedList; }, addPad: function(name) { if (!this.initiated) return; - if (this.list.indexOf(name) == -1) { - this.list.push(name); - this.sorted = false; + if (!this.list.has(name)) { + this.list.add(name); + this.cachedList = undefined; } }, removePad: function(name) { if (!this.initiated) return; - var index = this.list.indexOf(name); - - if (index > -1) { - this.list.splice(index, 1); - this.sorted = false; + if (this.list.has(name)) { + this.list.delete(name); + this.cachedList = undefined; } } }; diff --git a/src/node/db/SecurityManager.js b/src/node/db/SecurityManager.js index 23af82836c1..d0fc6645aaf 100644 --- a/src/node/db/SecurityManager.js +++ b/src/node/db/SecurityManager.js @@ -30,7 +30,10 @@ var authLogger = log4js.getLogger("auth"); * This function controlls the access to a pad, it checks if the user can access a pad. * @param padID the pad the user wants to access * @param sessionCookie the session the user has (set via api) - * @param token the token of the author (randomly generated at client side, used for public pads) + * @param token a random token representing the author, of the form + * t.randomstring_of_lenght_20. The random string is generated by + * the client. + * Used for every pad in the web UI. Not used for the HTTP API. * @param password the password the user has given to access this pad, can be null * @return {accessStatus: grant|deny|wrongPassword|needPassword, authorID: a.xxxxxx}) */ @@ -96,16 +99,39 @@ exports.checkAccess = async function(padID, sessionCookie, token, password) // get information about all sessions contained in this cookie if (sessionCookie) { let groupID = padID.split("$")[0]; - let sessionIDs = sessionCookie.split(','); + + /* + * Sometimes, RFC 6265-compliant web servers may send back a cookie whose + * value is enclosed in double quotes, such as: + * + * Set-Cookie: sessionCookie="s.37cf5299fbf981e14121fba3a588c02b,s.2b21517bf50729d8130ab85736a11346"; Version=1; Path=/; Domain=localhost; Discard + * + * Where the double quotes at the start and the end of the header value are + * just delimiters. This is perfectly legal: Etherpad parsing logic should + * cope with that, and remove the quotes early in the request phase. + * + * Somehow, this does not happen, and in such cases the actual value that + * sessionCookie ends up having is: + * + * sessionCookie = '"s.37cf5299fbf981e14121fba3a588c02b,s.2b21517bf50729d8130ab85736a11346"' + * + * As quick measure, let's strip the double quotes (when present). + * Note that here we are being minimal, limiting ourselves to just removing + * quotes at the start and the end of the string. + * + * Fixes #3819. + * Also, see #3820. + */ + let sessionIDs = sessionCookie.replace(/^"|"$/g, '').split(','); // was previously iterated in parallel using async.forEach - let sessionInfos = await Promise.all(sessionIDs.map(sessionID => { - return sessionManager.getSessionInfo(sessionID); - })); + try { + let sessionInfos = await Promise.all(sessionIDs.map(sessionID => { + return sessionManager.getSessionInfo(sessionID); + })); - // seperated out the iteration of sessioninfos from the (parallel) fetches from the DB - for (let sessionInfo of sessionInfos) { - try { + // seperated out the iteration of sessioninfos from the (parallel) fetches from the DB + for (let sessionInfo of sessionInfos) { // is it for this group? if (sessionInfo.groupID != groupID) { authLogger.debug("Auth failed: wrong group"); @@ -123,13 +149,13 @@ exports.checkAccess = async function(padID, sessionCookie, token, password) validSession = true; sessionAuthor = sessionInfo.authorID; break; - } catch (err) { - // skip session if it doesn't exist - if (err.message == "sessionID does not exist") { - authLogger.debug("Auth failed: unknown session"); - } else { - throw err; - } + } + } catch (err) { + // skip session if it doesn't exist + if (err.message == "sessionID does not exist") { + authLogger.debug("Auth failed: unknown session"); + } else { + throw err; } } } diff --git a/src/node/db/SessionStore.js b/src/node/db/SessionStore.js index 647cbbc8d9f..263c7d6eefe 100644 --- a/src/node/db/SessionStore.js +++ b/src/node/db/SessionStore.js @@ -38,6 +38,11 @@ SessionStore.prototype.get = function(sid, fn) { SessionStore.prototype.set = function(sid, sess, fn) { messageLogger.debug('SET ' + sid); + // don't store passwords in DB + if (sess.user && sess.user.password) { + sess.user.password = "PASSWORD_HIDDEN"; + } + db.set("sessionstorage:" + sid, sess); if (fn) { process.nextTick(fn); diff --git a/src/node/handler/APIHandler.js b/src/node/handler/APIHandler.js index 3898daaf5dc..cac8c15c51b 100644 --- a/src/node/handler/APIHandler.js +++ b/src/node/handler/APIHandler.js @@ -25,6 +25,7 @@ var log4js = require('log4js'); var padManager = require("../db/PadManager"); var randomString = require("../utils/randomstring"); var argv = require('../utils/Cli').argv; +var createHTTPError = require('http-errors'); var apiHandlerLogger = log4js.getLogger('APIHandler'); @@ -136,8 +137,13 @@ version["1.2.13"] = Object.assign({}, version["1.2.12"], } ); +version["1.2.14"] = Object.assign({}, version["1.2.13"], + { "getStats" : [] + } +); + // set the latest available API version here -exports.latestApiVersion = '1.2.13'; +exports.latestApiVersion = '1.2.14'; // exports the versions so it can be used by the new Swagger endpoint exports.version = version; @@ -153,25 +159,19 @@ exports.handle = async function(apiVersion, functionName, fields, req, res) { // say goodbye if this is an unknown API version if (!(apiVersion in version)) { - res.statusCode = 404; - res.send({code: 3, message: "no such api version", data: null}); - return; + throw new createHTTPError.NotFound('no such api version'); } // say goodbye if this is an unknown function if (!(functionName in version[apiVersion])) { - // no status code?! - res.send({code: 3, message: "no such function", data: null}); - return; + throw new createHTTPError.NotFound('no such function'); } // check the api key! fields["apikey"] = fields["apikey"] || fields["api_key"]; if (fields["apikey"] !== apikey.trim()) { - res.statusCode = 401; - res.send({code: 4, message: "no or wrong API Key", data: null}); - return; + throw new createHTTPError.Unauthorized('no or wrong API Key'); } // sanitize any padIDs before continuing @@ -185,37 +185,11 @@ exports.handle = async function(apiVersion, functionName, fields, req, res) fields["padName"] = await padManager.sanitizePadId(fields["padName"]); } - // no need to await - callAPI returns a promise - return callAPI(apiVersion, functionName, fields, req, res); -} - -// calls the api function -async function callAPI(apiVersion, functionName, fields, req, res) -{ // put the function parameters in an array var functionParams = version[apiVersion][functionName].map(function (field) { return fields[field] }); - try { - // call the api function - let data = await api[functionName].apply(this, functionParams); - - if (!data) { - data = null; - } - - res.send({code: 0, message: "ok", data: data}); - } catch (err) { - if (err.name == "apierror") { - // parameters were wrong and the api stopped execution, pass the error - - res.send({code: 1, message: err.message, data: null}); - } else { - // an unknown error happened - - res.send({code: 2, message: "internal error", data: null}); - throw err; - } - } + // call the api function + return api[functionName].apply(this, functionParams); } diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js index d2bd05289fa..e62cb94175f 100644 --- a/src/node/handler/ImportHandler.js +++ b/src/node/handler/ImportHandler.js @@ -72,6 +72,7 @@ async function doImport(req, res, padId) let form = new formidable.IncomingForm(); form.keepExtensions = true; form.uploadDir = tmpDirectory; + form.maxFileSize = settings.importMaxFileSize; // locally wrapped Promise, since form.parse requires a callback let srcFile = await new Promise((resolve, reject) => { @@ -81,9 +82,19 @@ async function doImport(req, res, padId) if (err) { console.warn("Uploading Error: " + err.stack); } + + // I hate doing indexOf here but I can't see anything to use... + if (err.stack.indexOf("maxFileSize") !== -1) { + reject("maxFileSize"); + } + + reject("uploadFailed"); + } + if(!files.file){ // might not be a graceful fix but it works reject("uploadFailed"); + }else{ + resolve(files.file.path); } - resolve(files.file.path); }); }); @@ -101,7 +112,7 @@ async function doImport(req, res, padId) let oldSrcFile = srcFile; srcFile = path.join(path.dirname(srcFile), path.basename(srcFile, fileEnding) + ".txt"); - await fs.rename(oldSrcFile, srcFile); + await fsp_rename(oldSrcFile, srcFile); } else { console.warn("Not allowing unknown file type to be imported", fileEnding); throw "uploadFailed"; @@ -111,7 +122,7 @@ async function doImport(req, res, padId) let destFile = path.join(tmpDirectory, "etherpad_import_" + randNum + "." + exportExtension); // Logic for allowing external Import Plugins - let result = await hooks.aCallAll("import", { srcFile, destFile }); + let result = await hooks.aCallAll("import", { srcFile, destFile, fileEnding }); let importHandledByPlugin = (result.length > 0); // This feels hacky and wrong.. let fileIsEtherpad = (fileEnding === ".etherpad"); @@ -181,8 +192,15 @@ async function doImport(req, res, padId) if (!req.directDatabaseAccess) { text = await fsp_readFile(destFile, "utf8"); - // Title needs to be stripped out else it appends it to the pad.. - text = text.replace("", "<!-- <title>"); + /* + * The <title> tag needs to be stripped out, otherwise it is appended to the + * pad. + * + * Moreover, when using LibreOffice to convert the file, some classes are + * added to the <title> tag. This is a quick & dirty way of matching the + * title and comment it out independently on the classes that are set on it. + */ + text = text.replace("<title", "<!-- <title"); text = text.replace("","-->"); // node on windows has a delay on releasing of the file lock. @@ -249,7 +267,7 @@ exports.doImport = function (req, res, padId) let status = "ok"; doImport(req, res, padId).catch(err => { // check for known errors and replace the status - if (err == "uploadFailed" || err == "convertFailed" || err == "padHasData") { + if (err == "uploadFailed" || err == "convertFailed" || err == "padHasData" || err == "maxFileSize") { status = err; } else { throw err; diff --git a/src/node/handler/PadMessageHandler.js b/src/node/handler/PadMessageHandler.js index ffbb74ea8da..9e23fea21d4 100644 --- a/src/node/handler/PadMessageHandler.js +++ b/src/node/handler/PadMessageHandler.js @@ -932,13 +932,23 @@ async function handleClientReady(client, message) await Promise.all(authors.map(authorId => { return authorManager.getAuthor(authorId).then(author => { if (!author) { - messageLogger.error("There is no author for authorId:", authorId); + messageLogger.error("There is no author for authorId: ", authorId, ". This is possibly related to https://github.com/ether/etherpad-lite/issues/2802"); } else { historicalAuthorData[authorId] = { name: author.name, colorId: author.colorId }; // Filter author attribs (e.g. don't send author's pads to all clients) } }); })); + let thisUserHasEditedThisPad = false; + if (historicalAuthorData[statusObject.authorID]) { + /* + * This flag is set to true when a user contributes to a specific pad for + * the first time. It is used for deciding if importing to that pad is + * allowed or not. + */ + thisUserHasEditedThisPad = true; + } + // glue the clientVars together, send them and tell the other clients that a new one is there // Check that the client is still here. It might have disconnected between callbacks. @@ -1065,6 +1075,7 @@ async function handleClientReady(client, message) // mile wide... var clientVars = { "skinName": settings.skinName, + "skinVariants": settings.skinVariants, "accountPrivs": { "maxRevisions": 100 }, @@ -1117,7 +1128,8 @@ async function handleClientReady(client, message) "scrollWhenCaretIsInTheLastLineOfViewport": settings.scrollWhenFocusLineIsOutOfViewport.scrollWhenCaretIsInTheLastLineOfViewport, "percentageToScrollWhenUserPressesArrowUp": settings.scrollWhenFocusLineIsOutOfViewport.percentageToScrollWhenUserPressesArrowUp, }, - "initialChangesets": [] // FIXME: REMOVE THIS SHIT + "initialChangesets": [], // FIXME: REMOVE THIS SHIT + "thisUserHasEditedThisPad": thisUserHasEditedThisPad, } // Add a username to the clientVars if one avaiable @@ -1189,6 +1201,28 @@ async function handleClientReady(client, message) let p = cached ? Promise.resolve(cached) : authorManager.getAuthor(author); return p.then(authorInfo => { + // default fallback color to use if authorInfo.colorId is null + const defaultColor = "#daf0b2"; + + if (!authorInfo) { + console.warn(`handleClientReady(): no authorInfo parameter was received. Default values are going to be used. See issue #3612. This can be caused by a user clicking undo after clearing all authorship colors see #2802`); + authorInfo = {}; + } + + // For some reason sometimes name isn't set + // Catch this issue here and use a fixed name. + if (!authorInfo.name) { + console.warn(`handleClientReady(): client submitted no author name. Using "Anonymous". See: issue #3612`); + authorInfo.name = "Anonymous"; + } + + // For some reason sometimes colorId isn't set + // Catch this issue here and use a fixed color. + if (!authorInfo.colorId) { + console.warn(`handleClientReady(): author "${authorInfo.name}" has no property colorId. Using the default color ${defaultColor}. See issue #3612`); + authorInfo.colorId = defaultColor; + } + // Send the new User a Notification about this other user let msg = { "type": "COLLABROOM", @@ -1407,11 +1441,12 @@ async function composePadChangesets (padId, startNum, endNum) })); // compose Changesets + let r; try { let changeset = changesets[startNum]; let pool = pad.apool(); - for (let r = startNum + 1; r < endNum; r++) { + for (r = startNum + 1; r < endNum; r++) { let cs = changesets[r]; changeset = Changeset.compose(changeset, cs, pool); } diff --git a/src/node/hooks/express.js b/src/node/hooks/express.js index 6394ffbfc15..7ff7d4ffc62 100644 --- a/src/node/hooks/express.js +++ b/src/node/hooks/express.js @@ -18,7 +18,13 @@ exports.createServer = function () { exports.restartServer(); - console.log(`You can access your Etherpad instance at http://${settings.ip}:${settings.port}/`); + if (settings.ip === "") { + // using Unix socket for connectivity + console.log(`You can access your Etherpad instance using the Unix socket at ${settings.port}`); + } else { + console.log(`You can access your Etherpad instance at http://${settings.ip}:${settings.port}/`); + } + if (!_.isEmpty(settings.users)) { console.log(`The plugin admin page is at http://${settings.ip}:${settings.port}/admin/plugins`); } else { @@ -94,6 +100,12 @@ exports.restartServer = function () { }); if (settings.trustProxy) { + /* + * If 'trust proxy' === true, the client’s IP address in req.ip will be the + * left-most entry in the X-Forwarded-* header. + * + * Source: https://expressjs.com/en/guide/behind-proxies.html + */ app.enable('trust proxy'); } diff --git a/src/node/hooks/express/apicalls.js b/src/node/hooks/express/apicalls.js index cf45074801b..c0967c35fea 100644 --- a/src/node/hooks/express/apicalls.js +++ b/src/node/hooks/express/apicalls.js @@ -1,49 +1,9 @@ var log4js = require('log4js'); -var apiLogger = log4js.getLogger("API"); var clientLogger = log4js.getLogger("client"); var formidable = require('formidable'); var apiHandler = require('../../handler/APIHandler'); -var isValidJSONPName = require('./isValidJSONPName'); - -//This is for making an api call, collecting all post information and passing it to the apiHandler -var apiCaller = function(req, res, fields) { - res.header("Content-Type", "application/json; charset=utf-8"); - - apiLogger.info("REQUEST, v"+ req.params.version + ":" + req.params.func + ", " + JSON.stringify(fields)); - - //wrap the send function so we can log the response - //note: res._send seems to be already in use, so better use a "unique" name - res._____send = res.send; - res.send = function (response) { - response = JSON.stringify(response); - apiLogger.info("RESPONSE, " + req.params.func + ", " + response); - - //is this a jsonp call, if yes, add the function call - if(req.query.jsonp && isValidJSONPName.check(req.query.jsonp)) - response = req.query.jsonp + "(" + response + ")"; - - res._____send(response); - } - - //call the api handler - apiHandler.handle(req.params.version, req.params.func, fields, req, res); -} - -exports.apiCaller = apiCaller; exports.expressCreateServer = function (hook_name, args, cb) { - //This is a api GET call, collect all post informations and pass it to the apiHandler - args.app.get('/api/:version/:func', function (req, res) { - apiCaller(req, res, req.query) - }); - - //This is a api POST call, collect all post informations and pass it to the apiHandler - args.app.post('/api/:version/:func', function(req, res) { - new formidable.IncomingForm().parse(req, function (err, fields, files) { - apiCaller(req, res, Object.assign(req.query, fields)) - }); - }); - //The Etherpad client side sends information about how a disconnect happened args.app.post('/ep/pad/connection-diagnostic-info', function(req, res) { new formidable.IncomingForm().parse(req, function(err, fields, files) { diff --git a/src/node/hooks/express/importexport.js b/src/node/hooks/express/importexport.js index ef10e0145a3..95d02775d48 100644 --- a/src/node/hooks/express/importexport.js +++ b/src/node/hooks/express/importexport.js @@ -3,8 +3,20 @@ var settings = require('../../utils/Settings'); var exportHandler = require('../../handler/ExportHandler'); var importHandler = require('../../handler/ImportHandler'); var padManager = require("../../db/PadManager"); +var authorManager = require("../../db/AuthorManager"); +const rateLimit = require("express-rate-limit"); + +settings.importExportRateLimiting.onLimitReached = function(req, res, options) { + // when the rate limiter triggers, write a warning in the logs + console.warn(`Import/Export rate limiter triggered on "${req.originalUrl}" for IP address ${req.ip}`); +} + +var limiter = rateLimit(settings.importExportRateLimiting); exports.expressCreateServer = function (hook_name, args, cb) { + + // handle export requests + args.app.use('/p/:pad/:rev?/export/:type', limiter); args.app.get('/p/:pad/:rev?/export/:type', async function(req, res, next) { var types = ["pdf", "doc", "txt", "html", "odt", "etherpad"]; //send a 404 if we don't support this filetype @@ -15,28 +27,77 @@ exports.expressCreateServer = function (hook_name, args, cb) { // if abiword is disabled, and this is a format we only support with abiword, output a message if (settings.exportAvailable() == "no" && ["odt", "pdf", "doc"].indexOf(req.params.type) !== -1) { - res.send("This export is not enabled at this Etherpad instance. Set the path to Abiword or SOffice in settings.json to enable this feature"); + console.error(`Impossible to export pad "${req.params.pad}" in ${req.params.type} format. There is no converter configured`); + + // ACHTUNG: do not include req.params.type in res.send() because there is no HTML escaping and it would lead to an XSS + res.send("This export is not enabled at this Etherpad instance. Set the path to Abiword or soffice (LibreOffice) in settings.json to enable this feature"); return; } res.header("Access-Control-Allow-Origin", "*"); if (await hasPadAccess(req, res)) { - console.log('req.params.pad', req.params.pad); let exists = await padManager.doesPadExists(req.params.pad); if (!exists) { + console.warn(`Someone tried to export a pad that doesn't exist (${req.params.pad})`); return next(); } + console.log(`Exporting pad "${req.params.pad}" in ${req.params.type} format`); exportHandler.doExport(req, res, req.params.pad, req.params.type); } }); // handle import requests + args.app.use('/p/:pad/import', limiter); args.app.post('/p/:pad/import', async function(req, res, next) { if (await hasPadAccess(req, res)) { let exists = await padManager.doesPadExists(req.params.pad); if (!exists) { + console.warn(`Someone tried to import into a pad that doesn't exist (${req.params.pad})`); + return next(); + } + + /* + * Starting from Etherpad 1.8.3 onwards, importing into a pad is allowed + * only if a user has his browser opened and connected to the pad (i.e. a + * Socket.IO session is estabilished for him) and he has already + * contributed to that specific pad. + * + * Note that this does not have anything to do with the "session", used + * for logging into "group pads". That kind of session is not needed here. + * + * This behaviour does not apply to API requests, only to /p/$PAD$/import + * + * See: https://github.com/ether/etherpad-lite/pull/3833#discussion_r407490205 + */ + if (!req.cookies) { + console.warn(`Unable to import file into "${req.params.pad}". No cookies included in request`); + return next(); + } + + if (!req.cookies.token) { + console.warn(`Unable to import file into "${req.params.pad}". No token in the cookies`); + return next(); + } + + let author = await authorManager.getAuthor4Token(req.cookies.token); + // author is of the form: "a.g2droBYw1prY7HW9" + if (!author) { + console.warn(`Unable to import file into "${req.params.pad}". No Author found for token ${req.cookies.token}`); + + return next(); + } + + let authorsPads = await authorManager.listPadsOfAuthor(author); + if (!authorsPads) { + console.warn(`Unable to import file into "${req.params.pad}". Author "${author}" exists but he never contributed to any pad`); + return next(); + } + + let authorsPadIDs = authorsPads.padIDs; + if (authorsPadIDs.indexOf(req.params.pad) === -1) { + console.warn(`Unable to import file into "${req.params.pad}". Author "${author}" exists but he never contributed to this pad`); return next(); } diff --git a/src/node/hooks/express/openapi.js b/src/node/hooks/express/openapi.js new file mode 100644 index 00000000000..26f898b963c --- /dev/null +++ b/src/node/hooks/express/openapi.js @@ -0,0 +1,707 @@ +/** + * node/hooks/express/openapi.js + * + * This module generates OpenAPI definitions for each API version defined by + * APIHandler.js and hooks into express to route the API using openapi-backend. + * + * The openapi definition files are publicly available under: + * + * - /api/openapi.json + * - /rest/openapi.json + * - /api/{version}/openapi.json + * - /rest/{version}/openapi.json + */ + +const OpenAPIBackend = require('openapi-backend').default; +const formidable = require('formidable'); +const { promisify } = require('util'); +const cloneDeep = require('lodash.clonedeep'); +const createHTTPError = require('http-errors'); + +const apiHandler = require('../../handler/APIHandler'); +const settings = require('../../utils/Settings'); +const isValidJSONPName = require('./isValidJSONPName'); + +const log4js = require('log4js'); +const apiLogger = log4js.getLogger('API'); + +// https://github.com/OAI/OpenAPI-Specification/tree/master/schemas/v3.0 +const OPENAPI_VERSION = '3.0.2'; // Swagger/OAS version + +const info = { + title: 'Etherpad API', + description: + 'Etherpad is a real-time collaborative editor scalable to thousands of simultaneous real time users. It provides full data export capabilities, and runs on your server, under your control.', + termsOfService: 'https://etherpad.org/', + contact: { + name: 'The Etherpad Foundation', + url: 'https://etherpad.org/', + email: 'support@example.com', + }, + license: { + name: 'Apache 2.0', + url: 'https://www.apache.org/licenses/LICENSE-2.0.html', + }, + version: apiHandler.latestApiVersion, +}; + +const APIPathStyle = { + FLAT: 'api', // flat paths e.g. /api/createGroup + REST: 'rest', // restful paths e.g. /rest/group/create +}; + +// API resources - describe your API endpoints here +const resources = { + // Group + group: { + create: { + operationId: 'createGroup', + summary: 'creates a new group', + responseSchema: { groupID: { type: 'string' } }, + }, + createIfNotExistsFor: { + operationId: 'createGroupIfNotExistsFor', + summary: 'this functions helps you to map your application group ids to Etherpad group ids', + responseSchema: { groupID: { type: 'string' } }, + }, + delete: { + operationId: 'deleteGroup', + summary: 'deletes a group', + }, + listPads: { + operationId: 'listPads', + summary: 'returns all pads of this group', + responseSchema: { padIDs: { type: 'array', items: { type: 'string' } } }, + }, + createPad: { + operationId: 'createGroupPad', + summary: 'creates a new pad in this group', + }, + listSessions: { + operationId: 'listSessionsOfGroup', + summary: '', + responseSchema: { sessions: { type: 'array', items: { $ref: '#/components/schemas/SessionInfo' } } }, + }, + list: { + operationId: 'listAllGroups', + summary: '', + responseSchema: { groupIDs: { type: 'array', items: { type: 'string' } } }, + }, + }, + + // Author + author: { + create: { + operationId: 'createAuthor', + summary: 'creates a new author', + responseSchema: { authorID: { type: 'string' } }, + }, + createIfNotExistsFor: { + operationId: 'createAuthorIfNotExistsFor', + summary: 'this functions helps you to map your application author ids to Etherpad author ids', + responseSchema: { authorID: { type: 'string' } }, + }, + listPads: { + operationId: 'listPadsOfAuthor', + summary: 'returns an array of all pads this author contributed to', + responseSchema: { padIDs: { type: 'array', items: { type: 'string' } } }, + }, + listSessions: { + operationId: 'listSessionsOfAuthor', + summary: 'returns all sessions of an author', + responseSchema: { sessions: { type: 'array', items: { $ref: '#/components/schemas/SessionInfo' } } }, + }, + // We need an operation that return a UserInfo so it can be picked up by the codegen :( + getName: { + operationId: 'getAuthorName', + summary: 'Returns the Author Name of the author', + responseSchema: { info: { $ref: '#/components/schemas/UserInfo' } }, + }, + }, + + // Session + session: { + create: { + operationId: 'createSession', + summary: 'creates a new session. validUntil is an unix timestamp in seconds', + responseSchema: { sessionID: { type: 'string' } }, + }, + delete: { + operationId: 'deleteSession', + summary: 'deletes a session', + }, + // We need an operation that returns a SessionInfo so it can be picked up by the codegen :( + info: { + operationId: 'getSessionInfo', + summary: 'returns informations about a session', + responseSchema: { info: { $ref: '#/components/schemas/SessionInfo' } }, + }, + }, + + // Pad + pad: { + listAll: { + operationId: 'listAllPads', + summary: 'list all the pads', + responseSchema: { padIDs: { type: 'array', items: { type: 'string' } } }, + }, + createDiffHTML: { + operationId: 'createDiffHTML', + summary: '', + responseSchema: {}, + }, + create: { + operationId: 'createPad', + description: + 'creates a new (non-group) pad. Note that if you need to create a group Pad, you should call createGroupPad', + }, + getText: { + operationId: 'getText', + summary: 'returns the text of a pad', + responseSchema: { text: { type: 'string' } }, + }, + setText: { + operationId: 'setText', + summary: 'sets the text of a pad', + }, + getHTML: { + operationId: 'getHTML', + summary: 'returns the text of a pad formatted as HTML', + responseSchema: { html: { type: 'string' } }, + }, + setHTML: { + operationId: 'setHTML', + summary: 'sets the text of a pad with HTML', + }, + getRevisionsCount: { + operationId: 'getRevisionsCount', + summary: 'returns the number of revisions of this pad', + responseSchema: { revisions: { type: 'integer' } }, + }, + getLastEdited: { + operationId: 'getLastEdited', + summary: 'returns the timestamp of the last revision of the pad', + responseSchema: { lastEdited: { type: 'integer' } }, + }, + delete: { + operationId: 'deletePad', + summary: 'deletes a pad', + }, + getReadOnlyID: { + operationId: 'getReadOnlyID', + summary: 'returns the read only link of a pad', + responseSchema: { readOnlyID: { type: 'string' } }, + }, + setPublicStatus: { + operationId: 'setPublicStatus', + summary: 'sets a boolean for the public status of a pad', + }, + getPublicStatus: { + operationId: 'getPublicStatus', + summary: 'return true of false', + responseSchema: { publicStatus: { type: 'boolean' } }, + }, + setPassword: { + operationId: 'setPassword', + summary: 'returns ok or a error message', + }, + isPasswordProtected: { + operationId: 'isPasswordProtected', + summary: 'returns true or false', + responseSchema: { passwordProtection: { type: 'boolean' } }, + }, + authors: { + operationId: 'listAuthorsOfPad', + summary: 'returns an array of authors who contributed to this pad', + responseSchema: { authorIDs: { type: 'array', items: { type: 'string' } } }, + }, + usersCount: { + operationId: 'padUsersCount', + summary: 'returns the number of user that are currently editing this pad', + responseSchema: { padUsersCount: { type: 'integer' } }, + }, + users: { + operationId: 'padUsers', + summary: 'returns the list of users that are currently editing this pad', + responseSchema: { padUsers: { type: 'array', items: { $ref: '#/components/schemas/UserInfo' } } }, + }, + sendClientsMessage: { + operationId: 'sendClientsMessage', + summary: 'sends a custom message of type msg to the pad', + }, + checkToken: { + operationId: 'checkToken', + summary: 'returns ok when the current api token is valid', + }, + getChatHistory: { + operationId: 'getChatHistory', + summary: 'returns the chat history', + responseSchema: { messages: { type: 'array', items: { $ref: '#/components/schemas/Message' } } }, + }, + // We need an operation that returns a Message so it can be picked up by the codegen :( + getChatHead: { + operationId: 'getChatHead', + summary: 'returns the chatHead (chat-message) of the pad', + responseSchema: { chatHead: { $ref: '#/components/schemas/Message' } }, + }, + appendChatMessage: { + operationId: 'appendChatMessage', + summary: 'appends a chat message', + }, + }, +}; + +const defaultResponses = { + Success: { + description: 'ok (code 0)', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + code: { + type: 'integer', + example: 0, + }, + message: { + type: 'string', + example: 'ok', + }, + data: { + type: 'object', + example: null, + }, + }, + }, + }, + }, + }, + ApiError: { + description: 'generic api error (code 1)', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + code: { + type: 'integer', + example: 1, + }, + message: { + type: 'string', + example: 'error message', + }, + data: { + type: 'object', + example: null, + }, + }, + }, + }, + }, + }, + InternalError: { + description: 'internal api error (code 2)', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + code: { + type: 'integer', + example: 2, + }, + message: { + type: 'string', + example: 'internal error', + }, + data: { + type: 'object', + example: null, + }, + }, + }, + }, + }, + }, + NotFound: { + description: 'no such function (code 4)', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + code: { + type: 'integer', + example: 3, + }, + message: { + type: 'string', + example: 'no such function', + }, + data: { + type: 'object', + example: null, + }, + }, + }, + }, + }, + }, + Unauthorized: { + description: 'no or wrong API key (code 4)', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + code: { + type: 'integer', + example: 4, + }, + message: { + type: 'string', + example: 'no or wrong API key', + }, + data: { + type: 'object', + example: null, + }, + }, + }, + }, + }, + }, +}; + +const defaultResponseRefs = { + 200: { + $ref: '#/components/responses/Success', + }, + 400: { + $ref: '#/components/responses/ApiError', + }, + 401: { + $ref: '#/components/responses/Unauthorized', + }, + 500: { + $ref: '#/components/responses/InternalError', + }, +}; + +// convert to a dictionary of operation objects +const operations = {}; +for (const resource in resources) { + for (const action in resources[resource]) { + const { operationId, responseSchema, ...operation } = resources[resource][action]; + + // add response objects + const responses = { ...defaultResponseRefs }; + if (responseSchema) { + responses[200] = cloneDeep(defaultResponses.Success); + responses[200].content['application/json'].schema.properties.data = { + type: 'object', + properties: responseSchema, + }; + } + + // add final operation object to dictionary + operations[operationId] = { + operationId, + ...operation, + responses, + tags: [resource], + _restPath: `/${resource}/${action}`, + }; + } +} + +const generateDefinitionForVersion = (version, style = APIPathStyle.FLAT) => { + const definition = { + openapi: OPENAPI_VERSION, + info, + paths: {}, + components: { + parameters: {}, + schemas: { + SessionInfo: { + type: 'object', + properties: { + id: { + type: 'string', + }, + authorID: { + type: 'string', + }, + groupID: { + type: 'string', + }, + validUntil: { + type: 'integer', + }, + }, + }, + UserInfo: { + type: 'object', + properties: { + id: { + type: 'string', + }, + colorId: { + type: 'string', + }, + name: { + type: 'string', + }, + timestamp: { + type: 'integer', + }, + }, + }, + Message: { + type: 'object', + properties: { + text: { + type: 'string', + }, + userId: { + type: 'string', + }, + userName: { + type: 'string', + }, + time: { + type: 'integer', + }, + }, + }, + }, + responses: { + ...defaultResponses, + }, + securitySchemes: { + ApiKey: { + type: 'apiKey', + in: 'query', + name: 'apikey', + }, + }, + }, + security: [{ ApiKey: [] }], + }; + + // build operations + for (const funcName in apiHandler.version[version]) { + let operation = {}; + if (operations[funcName]) { + operation = { ...operations[funcName] }; + } else { + // console.warn(`No operation found for function: ${funcName}`); + operation = { + operationId: funcName, + responses: defaultResponseRefs, + }; + } + + // set parameters + operation.parameters = operation.parameters || []; + for (const paramName of apiHandler.version[version][funcName]) { + operation.parameters.push({ $ref: `#/components/parameters/${paramName}` }); + if (!definition.components.parameters[paramName]) { + definition.components.parameters[paramName] = { + name: paramName, + in: 'query', + schema: { + type: 'string', + }, + }; + } + } + + // set path + let path = `/${operation.operationId}`; // APIPathStyle.FLAT + if (style === APIPathStyle.REST && operation._restPath) { + path = operation._restPath; + } + delete operation._restPath; + + // add to definition + // NOTE: It may be confusing that every operation can be called with both GET and POST + definition.paths[path] = { + get: { + ...operation, + operationId: `${operation.operationId}UsingGET`, + }, + post: { + ...operation, + operationId: `${operation.operationId}UsingPOST`, + }, + }; + } + return definition; +}; + +exports.expressCreateServer = async (_, args) => { + const { app } = args; + + // create openapi-backend handlers for each api version under /api/{version}/* + for (const version in apiHandler.version) { + // we support two different styles of api: flat + rest + // TODO: do we really want to support both? + + for (const style of [APIPathStyle.FLAT, APIPathStyle.REST]) { + const apiRoot = getApiRootForVersion(version, style); + + // generate openapi definition for this API version + const definition = generateDefinitionForVersion(version, style); + + // serve version specific openapi definition + app.get(`${apiRoot}/openapi.json`, (req, res) => { + // For openapi definitions, wide CORS is probably fine + res.header('Access-Control-Allow-Origin', '*'); + res.json({ ...definition, servers: [generateServerForApiVersion(apiRoot, req)] }); + }); + + // serve latest openapi definition file under /api/openapi.json + const isLatestAPIVersion = version === apiHandler.latestApiVersion; + if (isLatestAPIVersion) { + app.get(`/${style}/openapi.json`, (req, res) => { + res.header('Access-Control-Allow-Origin', '*'); + res.json({ ...definition, servers: [generateServerForApiVersion(apiRoot, req)] }); + }); + } + + // build openapi-backend instance for this api version + const api = new OpenAPIBackend({ + apiRoot, // each api version has its own root + definition, + validate: false, + // for a small optimisation, we can run the quick startup for older + // API versions since they are subsets of the latest api definition + quick: !isLatestAPIVersion, + }); + + // register default handlers + api.register({ + notFound: () => { + throw new createHTTPError.notFound('no such function'); + }, + notImplemented: () => { + throw new createHTTPError.notImplemented('function not implemented'); + }, + }); + + // register operation handlers + for (const funcName in apiHandler.version[version]) { + const handler = async (c, req, res) => { + // parse fields from request + const { header, params, query } = c.request; + + // read form data if method was POST + let formData = {}; + if (c.request.method === 'post') { + const form = new formidable.IncomingForm(); + const parseForm = promisify(form.parse).bind(form); + formData = await parseForm(req); + } + + const fields = Object.assign({}, header, params, query, formData); + + // log request + apiLogger.info(`REQUEST, v${version}:${funcName}, ${JSON.stringify(fields)}`); + + // pass to api handler + let data = await apiHandler.handle(version, funcName, fields, req, res).catch((err) => { + // convert all errors to http errors + if (err instanceof createHTTPError.HttpError) { + // pass http errors thrown by handler forward + throw err; + } else if (err.name == 'apierror') { + // parameters were wrong and the api stopped execution, pass the error + // convert to http error + throw new createHTTPError.BadRequest(err.message); + } else { + // an unknown error happened + // log it and throw internal error + apiLogger.error(err); + throw new createHTTPError.InternalError('internal error'); + } + }); + + // return in common format + let response = { code: 0, message: 'ok', data: data || null }; + + // log response + apiLogger.info(`RESPONSE, ${funcName}, ${JSON.stringify(response)}`); + + // return the response data + return response; + }; + + // each operation can be called with either GET or POST + api.register(`${funcName}UsingGET`, handler); + api.register(`${funcName}UsingPOST`, handler); + } + + // start and bind to express + api.init(); + app.use(apiRoot, async (req, res) => { + let response = null; + try { + if (style === APIPathStyle.REST) { + // @TODO: Don't allow CORS from everywhere + // This is purely to maintain compatibility with old swagger-node-express + res.header('Access-Control-Allow-Origin', '*'); + } + // pass to openapi-backend handler + response = await api.handleRequest(req, req, res); + } catch (err) { + // handle http errors + res.statusCode = err.statusCode || 500; + + // convert to our json response format + // https://github.com/ether/etherpad-lite/tree/master/doc/api/http_api.md#response-format + switch (res.statusCode) { + case 403: // forbidden + response = { code: 4, message: err.message, data: null }; + break; + case 401: // unauthorized (no or wrong api key) + response = { code: 4, message: err.message, data: null }; + break; + case 404: // not found (no such function) + response = { code: 3, message: err.message, data: null }; + break; + case 500: // server error (internal error) + response = { code: 2, message: err.message, data: null }; + break; + case 400: // bad request (wrong parameters) + // respond with 200 OK to keep old behavior and pass tests + res.statusCode = 200; // @TODO: this is bad api design + response = { code: 1, message: err.message, data: null }; + break; + default: + response = { code: 1, message: err.message, data: null }; + break; + } + } + + // support jsonp response format + if (req.query.jsonp && isValidJSONPName.check(req.query.jsonp)) { + res.header('Content-Type', 'application/javascript'); + response = `${req.query.jsonp}(${JSON.stringify(response)}`; + } + + // send response + return res.send(response); + }); + } + } +}; + +// helper to get api root +const getApiRootForVersion = (version, style = APIPathStyle.FLAT) => `/${style}/${version}`; + +// helper to generate an OpenAPI server object when serving definitions +const generateServerForApiVersion = (apiRoot, req) => ({ + url: `${settings.ssl ? 'https' : 'http'}://${req.headers.host}${apiRoot}`, +}); diff --git a/src/node/hooks/express/specialpages.js b/src/node/hooks/express/specialpages.js index 035074e0296..2ca1384bb6e 100644 --- a/src/node/hooks/express/specialpages.js +++ b/src/node/hooks/express/specialpages.js @@ -41,30 +41,6 @@ exports.expressCreateServer = function (hook_name, args, cb) { //serve pad.html under /p args.app.get('/p/:pad', function(req, res, next) { - // Set language for pad editor for the first time - // Or if language cookie doesn't exist - if (req.cookies.language === undefined) - { - cookieOptions = { - /* req.protocol may be 'https' because either: - * - * 1. we are directly serving the nodejs application over SSL, using - * the "ssl" options in settings.json - * - * 2. we are serving the nodejs application in plaintext, but we are - * using a reverse proxy that terminates SSL for us. In this case, - * the user has to set trustProxy = true in settings.json, and thus - * req.protocol will reflect the value of the X-Forwarded-Proto HTTP - * header - * - * Please note that this will not be compatible with applications being - * served over http and https at the same time. - */ - secure: (req.protocol === 'https'), - } - res.cookie('language', settings.padOptions.lang, cookieOptions); - } - // The below might break for pads being rewritten var isReadOnly = req.url.indexOf("/p/r.") === 0; diff --git a/src/node/hooks/express/swagger.js b/src/node/hooks/express/swagger.js deleted file mode 100644 index f3f07cd010f..00000000000 --- a/src/node/hooks/express/swagger.js +++ /dev/null @@ -1,443 +0,0 @@ -var express = require('express'); -var apiHandler = require('../../handler/APIHandler'); -var apiCaller = require('./apicalls').apiCaller; -var settings = require("../../utils/Settings"); - -var swaggerModels = { - 'models': { - 'SessionInfo' : { - "id": 'SessionInfo', - "properties": { - "id": { - "type": "string" - }, - "authorID": { - "type": "string" - }, - "groupID":{ - "type":"string" - }, - "validUntil":{ - "type":"long" - } - } - }, - 'UserInfo' : { - "id": 'UserInfo', - "properties": { - "id": { - "type": "string" - }, - "colorId": { - "type": "string" - }, - "name":{ - "type":"string" - }, - "timestamp":{ - "type":"long" - } - } - }, - 'Message' : { - "id": 'Message', - "properties": { - "text": { - "type": "string" - }, - "userId": { - "type": "string" - }, - "userName":{ - "type":"string" - }, - "time":{ - "type":"long" - } - } - } - } -}; - -function sessionListResponseProcessor(res) { - if (res.data) { - var sessions = []; - for (var sessionId in res.data) { - var sessionInfo = res.data[sessionId]; - sessionId["id"] = sessionId; - sessions.push(sessionInfo); - } - res.data = sessions; - } - - return res; -} - -// We'll add some more info to the API methods -var API = { - - // Group - "group": { - "create" : { - "func" : "createGroup", - "description": "creates a new group", - "response": {"groupID":{"type":"string"}} - }, - "createIfNotExistsFor" : { - "func": "createGroupIfNotExistsFor", - "description": "this functions helps you to map your application group ids to Etherpad group ids", - "response": {"groupID":{"type":"string"}} - }, - "delete" : { - "func": "deleteGroup", - "description": "deletes a group" - }, - "listPads" : { - "func": "listPads", - "description": "returns all pads of this group", - "response": {"padIDs":{"type":"List", "items":{"type":"string"}}} - }, - "createPad" : { - "func": "createGroupPad", - "description": "creates a new pad in this group" - }, - "listSessions": { - "func": "listSessionsOfGroup", - "responseProcessor": sessionListResponseProcessor, - "description": "", - "response": {"sessions":{"type":"List", "items":{"type":"SessionInfo"}}} - }, - "list": { - "func": "listAllGroups", - "description": "", - "response": {"groupIDs":{"type":"List", "items":{"type":"string"}}} - }, - }, - - // Author - "author": { - "create" : { - "func" : "createAuthor", - "description": "creates a new author", - "response": {"authorID":{"type":"string"}} - }, - "createIfNotExistsFor": { - "func": "createAuthorIfNotExistsFor", - "description": "this functions helps you to map your application author ids to Etherpad author ids", - "response": {"authorID":{"type":"string"}} - }, - "listPads": { - "func": "listPadsOfAuthor", - "description": "returns an array of all pads this author contributed to", - "response": {"padIDs":{"type":"List", "items":{"type":"string"}}} - }, - "listSessions": { - "func": "listSessionsOfAuthor", - "responseProcessor": sessionListResponseProcessor, - "description": "returns all sessions of an author", - "response": {"sessions":{"type":"List", "items":{"type":"SessionInfo"}}} - }, - // We need an operation that return a UserInfo so it can be picked up by the codegen :( - "getName" : { - "func": "getAuthorName", - "description": "Returns the Author Name of the author", - "responseProcessor": function(response) { - if (response.data) { - response["info"] = {"name": response.data.authorName}; - delete response["data"]; - } - }, - "response": {"info":{"type":"UserInfo"}} - } - }, - "session": { - "create" : { - "func": "createSession", - "description": "creates a new session. validUntil is an unix timestamp in seconds", - "response": {"sessionID":{"type":"string"}} - }, - "delete" : { - "func": "deleteSession", - "description": "deletes a session" - }, - // We need an operation that returns a SessionInfo so it can be picked up by the codegen :( - "info": { - "func": "getSessionInfo", - "description": "returns informations about a session", - "responseProcessor": function(response) { - // move this to info - if (response.data) { - response["info"] = response.data; - delete response["data"]; - } - }, - "response": {"info":{"type":"SessionInfo"}} - } - }, - "pad": { - "listAll" : { - "func": "listAllPads", - "description": "list all the pads", - "response": {"padIDs":{"type":"List", "items": {"type" : "string"}}} - }, - "createDiffHTML" : { - "func" : "createDiffHTML", - "description": "", - "response": {} - }, - "create" : { - "func" : "createPad", - "description": "creates a new (non-group) pad. Note that if you need to create a group Pad, you should call createGroupPad" - }, - "getText" : { - "func" : "getText", - "description": "returns the text of a pad", - "response": {"text":{"type":"string"}} - }, - "setText" : { - "func" : "setText", - "description": "sets the text of a pad" - }, - "getHTML": { - "func" : "getHTML", - "description": "returns the text of a pad formatted as HTML", - "response": {"html":{"type":"string"}} - }, - "setHTML": { - "func" : "setHTML", - "description": "sets the text of a pad with HTML" - }, - "getRevisionsCount": { - "func" : "getRevisionsCount", - "description": "returns the number of revisions of this pad", - "response": {"revisions":{"type":"long"}} - }, - "getLastEdited": { - "func" : "getLastEdited", - "description": "returns the timestamp of the last revision of the pad", - "response": {"lastEdited":{"type":"long"}} - }, - "delete": { - "func" : "deletePad", - "description": "deletes a pad" - }, - "getReadOnlyID": { - "func" : "getReadOnlyID", - "description": "returns the read only link of a pad", - "response": {"readOnlyID":{"type":"string"}} - }, - "setPublicStatus": { - "func": "setPublicStatus", - "description": "sets a boolean for the public status of a pad" - }, - "getPublicStatus": { - "func": "getPublicStatus", - "description": "return true of false", - "response": {"publicStatus":{"type":"boolean"}} - }, - "setPassword": { - "func": "setPassword", - "description": "returns ok or a error message" - }, - "isPasswordProtected": { - "func": "isPasswordProtected", - "description": "returns true or false", - "response": {"passwordProtection":{"type":"boolean"}} - }, - "authors": { - "func": "listAuthorsOfPad", - "description": "returns an array of authors who contributed to this pad", - "response": {"authorIDs":{"type":"List", "items":{"type" : "string"}}} - }, - "usersCount": { - "func": "padUsersCount", - "description": "returns the number of user that are currently editing this pad", - "response": {"padUsersCount":{"type": "long"}} - }, - "users": { - "func": "padUsers", - "description": "returns the list of users that are currently editing this pad", - "response": {"padUsers":{"type":"List", "items":{"type": "UserInfo"}}} - }, - "sendClientsMessage": { - "func": "sendClientsMessage", - "description": "sends a custom message of type msg to the pad" - }, - "checkToken" : { - "func": "checkToken", - "description": "returns ok when the current api token is valid" - }, - "getChatHistory": { - "func": "getChatHistory", - "description": "returns the chat history", - "response": {"messages":{"type":"List", "items": {"type" : "Message"}}} - }, - // We need an operation that returns a Message so it can be picked up by the codegen :( - "getChatHead": { - "func": "getChatHead", - "description": "returns the chatHead (chat-message) of the pad", - "responseProcessor": function(response) { - // move this to info - if (response.data) { - response["chatHead"] = {"time": response.data["chatHead"]}; - delete response["data"]; - } - }, - "response": {"chatHead":{"type":"Message"}} - }, - "appendChatMessage": { - "func": "appendChatMessage", - "description": "appends a chat message" - } - } -}; - -function capitalise(string){ - return string.charAt(0).toUpperCase() + string.slice(1); -} - -for (var resource in API) { - for (var func in API[resource]) { - - // The base response model - var responseModel = { - "properties": { - "code":{ - "type":"int" - }, - "message":{ - "type":"string" - } - } - }; - - var responseModelId = "Response"; - - // Add the data properties (if any) to the response - if (API[resource][func]["response"]) { - // This is a specific response so let's set a new id - responseModelId = capitalise(resource) + capitalise(func) + "Response"; - - for(var prop in API[resource][func]["response"]) { - var propType = API[resource][func]["response"][prop]; - responseModel["properties"][prop] = propType; - } - } - - // Add the id - responseModel["id"] = responseModelId; - - // Add this to the swagger models - swaggerModels['models'][responseModelId] = responseModel; - - // Store the response model id - API[resource][func]["responseClass"] = responseModelId; - - } -} - -function newSwagger() { - var swagger_module = require.resolve("swagger-node-express"); - if (require.cache[swagger_module]) { - // delete the child modules from cache - require.cache[swagger_module].children.forEach(function(m) {delete require.cache[m.id];}); - // delete the module from cache - delete require.cache[swagger_module]; - } - return require("swagger-node-express"); -} - -exports.expressCreateServer = function (hook_name, args, cb) { - - for (var version in apiHandler.version) { - - var swagger = newSwagger(); - var basePath = "/rest/" + version; - - // Let's put this under /rest for now - var subpath = express(); - - args.app.use(basePath, subpath); - - //hack! - var swagger_temp = swagger - swagger = swagger.createNew(subpath); - swagger.params = swagger_temp.params - swagger.queryParam = swagger_temp.queryParam - swagger.pathParam = swagger_temp.pathParam - swagger.bodyParam = swagger_temp.bodyParam - swagger.formParam = swagger_temp.formParam - swagger.headerParam = swagger_temp.headerParam - swagger.error = swagger_temp.error - //swagger.setAppHandler(subpath); - - swagger.addModels(swaggerModels); - - for (var resource in API) { - - for (var funcName in API[resource]) { - var func = API[resource][funcName]; - - // get the api function - var apiFunc = apiHandler.version[version][func["func"]]; - - // Skip this one if it does not exist in the version - if(!apiFunc) { - continue; - } - - var swaggerFunc = { - 'spec': { - "description" : func["description"], - "path" : "/" + resource + "/" + funcName, - "summary" : funcName, - "nickname" : funcName, - "method": "GET", - "params" : apiFunc.map( function(param) { - return swagger.queryParam(param, param, "string"); - }), - "responseClass" : func["responseClass"] - }, - 'action': (function(func, responseProcessor) { - return function (req,res) { - req.params.version = version; - req.params.func = func; // call the api function - - //wrap the send function so we can process the response - res.__swagger_send = res.send; - res.send = function (response) { - // ugly but we need to get this as json - response = JSON.parse(response); - // process the response if needed - if (responseProcessor) { - response = responseProcessor(response); - } - // Let's move everything out of "data" - if (response.data) { - for(var prop in response.data) { - response[prop] = response.data[prop]; - delete response.data; - } - } - response = JSON.stringify(response); - res.__swagger_send(response); - }; - - apiCaller(req, res, req.query); - }; - })(func["func"], func["responseProcessor"]) // must use a closure here - }; - - swagger.addGet(swaggerFunc); - } - } - - swagger.setHeaders = function setHeaders(res) { - res.header('Access-Control-Allow-Origin', "*"); - }; - - swagger.configureSwaggerPaths("", "/api" , ""); - - swagger.configure("http://" + settings.ip + ":" + settings.port + basePath, version); - } -}; diff --git a/src/node/hooks/express/tests.js b/src/node/hooks/express/tests.js index 443e9f685b8..efc03fa489d 100644 --- a/src/node/hooks/express/tests.js +++ b/src/node/hooks/express/tests.js @@ -12,6 +12,10 @@ exports.expressCreateServer = function (hook_name, args, cb) { // merge the two sets of results let files = [].concat(coreTests, pluginTests).sort(); + + // Remove swap files from tests + files = files.filter(el => !/\.swp$/.test(el)) + console.debug("Sent browser the following test specs:", files); res.send("var specs_list = " + JSON.stringify(files) + ";\n"); }); @@ -54,7 +58,7 @@ exports.expressCreateServer = function (hook_name, args, cb) { }); args.app.get('/tests/frontend', function (req, res) { - res.redirect('/tests/frontend/'); + res.redirect('/tests/frontend/index.html'); }); } diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index 01a040258a3..ffb132ae1ad 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -126,7 +126,7 @@ exports.expressConfigure = function (hook_name, args, cb) { args.app.use(sessionModule({ secret: exports.secret, store: args.app.sessionStore, - resave: true, + resave: false, saveUninitialized: true, name: 'express_sid', proxy: true, diff --git a/src/node/server.js b/src/node/server.js index 8e57b39975e..d98767225fb 100755 --- a/src/node/server.js +++ b/src/node/server.js @@ -31,7 +31,7 @@ log4js.replaceConsole(); * early check for version compatibility before calling * any modules that require newer versions of NodeJS */ -NodeVersion.enforceMinNodeVersion('8.9.0'); +NodeVersion.enforceMinNodeVersion('10.13.0'); /* * Etherpad 1.8.3 will require at least nodejs 10.13.0. diff --git a/src/node/utils/LibreOffice.js b/src/node/utils/LibreOffice.js index d72b9324920..267f7a0cd0a 100644 --- a/src/node/utils/LibreOffice.js +++ b/src/node/utils/LibreOffice.js @@ -38,6 +38,14 @@ var libreOfficeLogger = log4js.getLogger('LibreOffice'); * @param {Function} callback Standard callback function */ exports.convertFile = function(srcFile, destFile, type, callback) { + // Used for the moving of the file, not the conversion + var fileExtension = type; + + if (type === "html") { + // "html:XHTML Writer File:UTF8" does a better job than normal html exports + type = "html:XHTML Writer File:UTF8"; + } + // soffice can't convert from html to doc directly (verified with LO 5 and 6) // we need to convert to odt first, then to doc // to avoid `Error: no export filter for /tmp/xxxx.doc` error @@ -47,11 +55,11 @@ exports.convertFile = function(srcFile, destFile, type, callback) { "destFile": destFile.replace(/\.doc$/, '.odt'), "type": 'odt', "callback": function () { - queue.push({"srcFile": srcFile.replace(/\.html$/, '.odt'), "destFile": destFile, "type": type, "callback": callback}); + queue.push({"srcFile": srcFile.replace(/\.html$/, '.odt'), "destFile": destFile, "type": type, "callback": callback, "fileExtension": fileExtension }); } }); } else { - queue.push({"srcFile": srcFile, "destFile": destFile, "type": type, "callback": callback}); + queue.push({"srcFile": srcFile, "destFile": destFile, "type": type, "callback": callback, "fileExtension": fileExtension}); } }; @@ -102,7 +110,7 @@ function doConvertTask(task, callback) { // Move the converted file to the correct place function(callback) { var filename = path.basename(task.srcFile); - var sourceFilename = filename.substr(0, filename.lastIndexOf('.')) + '.' + task.type; + var sourceFilename = filename.substr(0, filename.lastIndexOf('.')) + '.' + task.fileExtension; var sourcePath = path.join(tmpDir, sourceFilename); libreOfficeLogger.debug(`Renaming ${sourcePath} to ${task.destFile}`); fs.rename(sourcePath, task.destFile, callback); diff --git a/src/node/utils/Minify.js b/src/node/utils/Minify.js index 45aecd24a3c..7cc05645bf4 100644 --- a/src/node/utils/Minify.js +++ b/src/node/utils/Minify.js @@ -276,7 +276,7 @@ function getAceFile(callback) { data += 'Ace2Editor.EMBEDED[' + JSON.stringify(filename) + '] = ' + JSON.stringify(status == 200 ? body || '' : null) + ';\n'; } else { - // Silence? + console.error(`getAceFile(): error getting ${resourceURI}. Status code: ${status}`); } callback(); }); @@ -382,8 +382,14 @@ function getFileCompressed(filename, contentType, callback) { } else if (contentType == 'text/javascript') { try { content = compressJS(content); + if (content.error) { + console.error(`Error compressing JS (${filename}) using UglifyJS`, content.error); + callback('compressionError', content.error); + } else { + content = content.code.toString(); // Convert content obj code to string + } } catch (error) { - // silence + console.error(`getFile() returned an error in getFileCompressed(${filename}, ${contentType}): ${error}`); } callback(null, content); } else if (contentType == 'text/css') { @@ -406,26 +412,53 @@ function getFile(filename, callback) { function compressJS(content) { - var decoder = new StringDecoder('utf8'); - var code = decoder.write(content); // convert from buffer to string - var codeMinified = uglifyJS.minify(code, {fromString: true}).code; - return codeMinified; + const contentAsString = content.toString(); + const codeObj = uglifyJS.minify(contentAsString); + + return codeObj; } function compressCSS(filename, content, callback) { try { - var base = path.join(ROOT_DIR, path.dirname(filename)); - new CleanCSS({relativeTo: base}).minify(content, function (errors, minified) { + const absPath = path.join(ROOT_DIR, filename); + + /* + * Changes done to migrate CleanCSS 3.x -> 4.x: + * + * 1. Disabling rebase is necessary because otherwise the URLs for the web + * fonts become wrong. + * + * EXAMPLE 1: + * /static/css/src/static/font/fontawesome-etherpad.woff + * instead of + * /static/font/fontawesome-etherpad.woff + * EXAMPLE 2 (this is more surprising): + * /p/src/static/font/opendyslexic.otf + * instead of + * /static/font/opendyslexic.otf + * + * 2. CleanCSS.minify() can either receive a string containing the CSS, or + * an array of strings. In that case each array element is interpreted as + * an absolute local path from which the CSS file is read. + * + * In version 4.x, CleanCSS API was simplified, eliminating the + * relativeTo parameter, and thus we cannot use our already loaded + * "content" argument, but we have to wrap the absolute path to the CSS + * in an array and ask the library to read it by itself. + */ + new CleanCSS({rebase: false}).minify([absPath], function (errors, minified) { if (errors) { - // On error, just yield the un-minified original. + // on error, just yield the un-minified original, but write a log message + console.error(`CleanCSS.minify() returned an error on ${filename} (${absPath}): ${errors}`); callback(null, content); } else { callback(null, minified.styles); } }); } catch (error) { - // On error, just yield the un-minified original. + // on error, just yield the un-minified original, but write a log message + console.error(`Unexpected error minifying ${filename} (${absPath}): ${error}`); callback(null, content); } } diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.js index 28d165fe6c3..369a4485f5f 100644 --- a/src/node/utils/Settings.js +++ b/src/node/utils/Settings.js @@ -1,6 +1,13 @@ /** - * The Settings Modul reads the settings out of settings.json and provides + * The Settings module reads the settings out of settings.json and provides * this information to the other modules + * + * TODO muxator 2020-04-14: + * + * 1) get rid of the reloadSettings() call at module loading; + * 2) provide a factory method that configures the settings module at runtime, + * reading the file name either from command line parameters, from a function + * argument, or falling back to a default. */ /* @@ -55,6 +62,8 @@ exports.faviconTimeslider = "../../" + exports.favicon; */ exports.skinName = null; +exports.skinVariants = "super-light-toolbar super-light-editor light-background"; + /** * The IP ep-lite should listen to */ @@ -298,6 +307,31 @@ exports.scrollWhenFocusLineIsOutOfViewport = { */ exports.exposeVersion = false; +/* + * From Etherpad 1.8.3 onwards, import and export of pads is always rate + * limited. + * + * The default is to allow at most 10 requests per IP in a 90 seconds window. + * After that the import/export request is rejected. + * + * See https://github.com/nfriedly/express-rate-limit for more options + */ +exports.importExportRateLimiting = { + // duration of the rate limit window (milliseconds) + "windowMs": 90000, + + // maximum number of requests per IP to allow during the rate limit window + "max": 10 +}; + +/* + * From Etherpad 1.8.3 onwards, the maximum allowed size for a single imported + * file is always bounded. + * + * File size is specified in bytes. Default is 50 MB. + */ +exports.importMaxFileSize = 50 * 1024 * 1024; + // checks if abiword is avaiable exports.abiwordAvailable = function() { @@ -333,7 +367,7 @@ exports.exportAvailable = function() { exports.getGitCommit = function() { var version = ""; try { - var rootPath = path.resolve(npm.dir, '..'); + var rootPath = exports.root; if (fs.lstatSync(rootPath + '/.git').isFile()) { rootPath = fs.readFileSync(rootPath + '/.git', "utf8"); rootPath = rootPath.split(' ').pop().trim(); @@ -387,6 +421,14 @@ function storeSettings(settingsObj) { /* * If stringValue is a numeric string, or its value is "true" or "false", coerce * them to appropriate JS types. Otherwise return stringValue as-is. + * + * Please note that this function is used for converting types for default + * values in the settings file (for example: "${PORT:9001}"), and that there is + * no coercition for "null" values. + * + * If the user wants a variable to be null by default, he'll have to use the + * short syntax "${ABIWORD}", and not "${ABIWORD:null}": the latter would result + * in the literal string "null", instead. */ function coerceValue(stringValue) { // cooked from https://stackoverflow.com/questions/175739/built-in-way-in-javascript-to-check-if-a-string-is-a-valid-number @@ -474,7 +516,7 @@ function lookupEnvironmentVariables(obj) { * "${ENV_VAR}" or "${ENV_VAR:default_value}") */ // MUXATOR 2019-03-21: we could use named capture groups here once we migrate to nodejs v10 - const match = value.match(/^\$\{([^:]*)(:(.*))?\}$/); + const match = value.match(/^\$\{([^:]*)(:((.|\n)*))?\}$/); if (match === null) { // no match: use the value literally, without any substitution @@ -491,7 +533,7 @@ function lookupEnvironmentVariables(obj) { const defaultValue = match[3]; if ((envVarValue === undefined) && (defaultValue === undefined)) { - console.warn(`Environment variable "${envVarName}" does not contain any value for configuration key "${key}", and no default was given. Returning null. Please check your configuration and environment settings.`); + console.warn(`Environment variable "${envVarName}" does not contain any value for configuration key "${key}", and no default was given. Returning null.`); /* * We have to return null, because if we just returned undefined, the @@ -594,19 +636,19 @@ exports.reloadSettings = function reloadSettings() { log4js.replaceConsole(); if (!exports.skinName) { - console.warn(`No "skinName" parameter found. Please check out settings.json.template and update your settings.json. Falling back to the default "no-skin".`); - exports.skinName = "no-skin"; + console.warn(`No "skinName" parameter found. Please check out settings.json.template and update your settings.json. Falling back to the default "colibris".`); + exports.skinName = "colibris"; } - // checks if skinName has an acceptable value, otherwise falls back to "no-skin" + // checks if skinName has an acceptable value, otherwise falls back to "colibris" if (exports.skinName) { const skinBasePath = path.join(exports.root, "src", "static", "skins"); const countPieces = exports.skinName.split(path.sep).length; if (countPieces != 1) { - console.error(`skinName must be the name of a directory under "${skinBasePath}". This is not valid: "${exports.skinName}". Falling back to the default "no-skin".`); + console.error(`skinName must be the name of a directory under "${skinBasePath}". This is not valid: "${exports.skinName}". Falling back to the default "colibris".`); - exports.skinName = "no-skin"; + exports.skinName = "colibris"; } // informative variable, just for the log messages @@ -614,15 +656,15 @@ exports.reloadSettings = function reloadSettings() { // what if someone sets skinName == ".." or "."? We catch him! if (absolutePaths.isSubdir(skinBasePath, skinPath) === false) { - console.error(`Skin path ${skinPath} must be a subdirectory of ${skinBasePath}. Falling back to the default "no-skin".`); + console.error(`Skin path ${skinPath} must be a subdirectory of ${skinBasePath}. Falling back to the default "colibris".`); - exports.skinName = "no-skin"; + exports.skinName = "colibris"; skinPath = path.join(skinBasePath, exports.skinName); } if (fs.existsSync(skinPath) === false) { - console.error(`Skin path ${skinPath} does not exist. Falling back to the default "no-skin".`); - exports.skinName = "no-skin"; + console.error(`Skin path ${skinPath} does not exist. Falling back to the default "colibris".`); + exports.skinName = "colibris"; skinPath = path.join(skinBasePath, exports.skinName); } @@ -631,26 +673,50 @@ exports.reloadSettings = function reloadSettings() { if (exports.users) { /* - * Prune from export.users any user that has no password attribute, or whose - * password attribute is "null". + * Each user must have exactly one of ("password", "hash") attributes set, + * and its value must be not null. * - * This is used by the settings.json in the default Dockerfile to eschew - * creating an admin user if no password is set. + * Prune from export.users any user that does not satisfy this condition, + * including the ones that (by chance) have both "password" and "hash" set. + * + * This mechanism is used by the settings.json in the default Dockerfile to + * eschew creating an admin user if no password (or hash) is set. */ var filteredUsers = _.pick(exports.users, function(userProperties, username) { - if (userProperties.hasOwnProperty("password") === false) { - console.warn(`Removing user "${username}", because it has no "password" field.`); + if ((userProperties.hasOwnProperty("password") === false) && (userProperties.hasOwnProperty("hash") === false)) { + console.warn(`Removing user "${username}", because it has no "password" or "hash" field.`); + + return false; + } + + if (userProperties.hasOwnProperty("password") && userProperties.hasOwnProperty("hash")) { + console.warn(`Removing user "${username}", because it has both "password" and "hash" fields set. THIS SHOULD NEVER HAPPEN.`); return false; } - if (userProperties.password === null) { - console.warn(`Removing user "${username}", because its password is null.`); + /* + * If we arrive here, the user has exactly a password or a hash set. + * They may still be null + */ + if (userProperties.hasOwnProperty("password") && (userProperties.password === null)) { + console.warn(`Removing user "${username}", because its "password" is null.`); return false; } - // This user has a password, and its password is not null. Keep it. + if (userProperties.hasOwnProperty("hash") && (userProperties.hash === null)) { + console.warn(`Removing user "${username}", because its "hash" value is null.`); + + return false; + } + + /* + * This user has a password, and its password is not null, or it has an + * hash, and its hash is not null (not both). + * + * Keep it. + */ return true; }); @@ -698,7 +764,7 @@ exports.reloadSettings = function reloadSettings() { fs.writeFileSync(sessionkeyFilename,exports.sessionKey,"utf8"); } } else { - console.warn("Declaring the sessionKey in the settings.json is deprecated. This value is auto-generated now. Please remove the setting from the file."); + console.warn("Declaring the sessionKey in the settings.json is deprecated. This value is auto-generated now. Please remove the setting from the file. -- If you are seeing this error after restarting using the Admin User Interface then you can ignore this message."); } if (exports.dbType === "dirty") { @@ -710,6 +776,11 @@ exports.reloadSettings = function reloadSettings() { exports.dbSettings.filename = absolutePaths.makeAbsolute(exports.dbSettings.filename); console.warn(dirtyWarning + ` File location: ${exports.dbSettings.filename}`); } + + if (exports.ip === "") { + // using Unix socket for connectivity + console.warn(`The settings file contains an empty string ("") for the "ip" parameter. The "port" parameter will be interpreted as the path to a Unix socket to bind at.`); + } }; // initially load settings diff --git a/src/node/utils/caching_middleware.js b/src/node/utils/caching_middleware.js index c01a95fb32d..bc387ca2c68 100644 --- a/src/node/utils/caching_middleware.js +++ b/src/node/utils/caching_middleware.js @@ -23,11 +23,55 @@ var settings = require('./Settings'); var semver = require('semver'); var existsSync = require('./path_exists'); +/* + * The crypto module can be absent on reduced node installations. + * + * Here we copy the approach TypeScript guys used for https://github.com/microsoft/TypeScript/issues/19100 + * If importing crypto fails at runtime, we replace sha256 with djb2, which is + * weaker, but works for our case. + * + * djb2 was written in 1991 by Daniel J. Bernstein. + * + */ + +// MIMIC https://github.com/microsoft/TypeScript/commit/9677b0641cc5ba7d8b701b4f892ed7e54ceaee9a - START +let _crypto; + +try { + _crypto = require('crypto'); +} catch { + _crypto = undefined; +} + var CACHE_DIR = path.normalize(path.join(settings.root, 'var/')); CACHE_DIR = existsSync(CACHE_DIR) ? CACHE_DIR : undefined; var responseCache = {}; +function djb2Hash(data) { + const chars = data.split("").map(str => str.charCodeAt(0)); + return `${chars.reduce((prev, curr) => ((prev << 5) + prev) + curr, 5381)}`; +} + +function generateCacheKeyWithSha256(path) { + return _crypto.createHash('sha256').update(path).digest('hex'); +} + +function generateCacheKeyWithDjb2(path) { + return Buffer.from(djb2Hash(path)).toString('hex'); +} + +let generateCacheKey; + +if (_crypto) { + generateCacheKey = generateCacheKeyWithSha256; +} else { + generateCacheKey = generateCacheKeyWithDjb2; + console.warn('No crypto support in this nodejs runtime. A fallback to Djb2 (weaker) will be used.'); +} + +// MIMIC https://github.com/microsoft/TypeScript/commit/9677b0641cc5ba7d8b701b4f892ed7e54ceaee9a - END + /* This caches and compresses 200 and 404 responses to GET and HEAD requests. TODO: Caching and compressing are solved problems, a middleware configuration @@ -49,7 +93,7 @@ CachingMiddleware.prototype = new function () { (req.get('Accept-Encoding') || '').indexOf('gzip') != -1; var path = require('url').parse(req.url).path; - var cacheKey = Buffer.from(path).toString('base64').replace(/[/+=]/g, ''); + var cacheKey = generateCacheKey(path); fs.stat(CACHE_DIR + 'minified_' + cacheKey, function (error, stats) { var modifiedSince = (req.headers['if-modified-since'] diff --git a/src/node/utils/customError.js b/src/node/utils/customError.js index c18743485bc..c47729f7f44 100644 --- a/src/node/utils/customError.js +++ b/src/node/utils/customError.js @@ -1,17 +1,23 @@ -/* - This helper modules allows us to create different type of errors we can throw -*/ -function customError(message, errorName) -{ - this.name = errorName || "Error"; - this.message = message; - - var stackParts = new Error().stack.split("\n"); - stackParts.splice(0,2); - stackParts.unshift(this.name + ": " + message); - - this.stack = stackParts.join("\n"); +/** + * CustomError + * + * This helper modules allows us to create different type of errors we can throw + * + * @class CustomError + * @extends {Error} + */ +class CustomError extends Error { + /** + * Creates an instance of CustomError. + * @param {*} message + * @param {string} [name='Error'] a custom name for the error object + * @memberof CustomError + */ + constructor(message, name = 'Error') { + super(message); + this.name = name; + Error.captureStackTrace(this, this.constructor); + } } -customError.prototype = Error.prototype; -module.exports = customError; +module.exports = CustomError; diff --git a/src/node/utils/promises.js b/src/node/utils/promises.js new file mode 100644 index 00000000000..4fb2e8318a4 --- /dev/null +++ b/src/node/utils/promises.js @@ -0,0 +1,32 @@ +/** + * Helpers to manipulate promises (like async but for promises). + */ + +var timesLimit = function (ltMax, concurrency, promiseCreator) { + var done = 0 + var current = 0 + + function addAnother () { + function _internalRun () { + done++ + + if (done < ltMax) { + addAnother() + } + } + + promiseCreator(current) + .then(_internalRun) + .catch(_internalRun) + + current++ + } + + for (var i = 0; i < concurrency && i < ltMax; i++) { + addAnother() + } +} + +module.exports = { + timesLimit: timesLimit +} diff --git a/src/node/utils/toolbar.js b/src/node/utils/toolbar.js index 67ce12593bd..a2b8f557935 100644 --- a/src/node/utils/toolbar.js +++ b/src/node/utils/toolbar.js @@ -68,7 +68,7 @@ ButtonsGroup.prototype.addButton = function (button) { }; ButtonsGroup.prototype.render = function () { - if (this.buttons.length == 1) { + if (this.buttons && this.buttons.length == 1) { this.buttons[0].grouping = ""; } else { @@ -80,7 +80,7 @@ ButtonsGroup.prototype.render = function () { } return _.map(this.buttons, function (btn) { - return btn.render(); + if(btn) return btn.render(); }).join("\n"); }; @@ -90,11 +90,16 @@ Button = function (attributes) { Button.load = function (btnName) { var button = module.exports.availableButtons[btnName]; - if (button.constructor === Button || button.constructor === SelectButton) { - return button; - } - else { - return new Button(button); + try{ + if (button.constructor === Button || button.constructor === SelectButton) { + return button; + } + else { + return new Button(button); + } + }catch(e){ + console.warn("Error loading button", btnName); + return false; } }; @@ -245,16 +250,36 @@ module.exports = { selectButton: function (attributes) { return new SelectButton(attributes); }, - menu: function (buttons, isReadOnly) { - if(isReadOnly){ + + /* + * Valid values for whichMenu: 'left' | 'right' | 'timeslider-right' + * Valid values for page: 'pad' | 'timeslider' + */ + menu: function (buttons, isReadOnly, whichMenu, page) { + if (isReadOnly) { // The best way to detect if it's the left editbar is to check for a bold button - if(buttons[0].indexOf("bold") !== -1){ + if (buttons[0].indexOf("bold") !== -1) { // Clear all formatting buttons - buttons = [] - }else{ + buttons = []; + } else { // Remove Save Revision from the right menu removeItem(buttons[0],"savedrevision"); } + } else { + /* + * This pad is not read only + * + * Add back the savedrevision button (the "star") if is not already there, + * but only on the right toolbar, and only if we are showing a pad (dont't + * do it in the timeslider). + * + * This is a quick fix for #3702 (and subsequent issue #3767): it was + * sufficient to visit a single read only pad to cause the disappearence + * of the star button from all the pads. + */ + if ((buttons[0].indexOf("savedrevision") === -1) && (whichMenu === "right") && (page === "pad")) { + buttons[0].push("savedrevision"); + } } var groups = _.map(buttons, function (group) { diff --git a/src/package-lock.json b/src/package-lock.json index 20036c85d6e..2d3edf937ca 100644 --- a/src/package-lock.json +++ b/src/package-lock.json @@ -1,25 +1,115 @@ { "name": "ep_etherpad-lite", - "version": "1.8.0-beta.1", + "version": "1.8.0", "lockfileVersion": 1, "requires": true, "dependencies": { + "@apidevtools/json-schema-ref-parser": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-8.0.0.tgz", + "integrity": "sha512-n4YBtwQhdpLto1BaUCyAeflizmIbaloGShsPyRtFf5qdFJxfssj+GgLavczgKJFa3Bq+3St2CKcpRJdjtB4EBw==", + "requires": { + "@jsdevtools/ono": "^7.1.0", + "call-me-maybe": "^1.0.1", + "js-yaml": "^3.13.1" + } + }, + "@apidevtools/openapi-schemas": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.0.3.tgz", + "integrity": "sha512-QoPaxGXfgqgGpK1p21FJ400z56hV681a8DOcZt3J5z0WIHgFeaIZ4+6bX5ATqmOoCpRCsH4ITEwKaOyFMz7wOA==" + }, + "@apidevtools/swagger-methods": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.1.tgz", + "integrity": "sha512-1Vlm18XYW6Yg7uHunroXeunWz5FShPFAdxBbPy8H6niB2Elz9QQsCoYHMbcc11EL1pTxaIr9HXz2An/mHXlX1Q==" + }, + "@apidevtools/swagger-parser": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-9.0.1.tgz", + "integrity": "sha512-Irqybg4dQrcHhZcxJc/UM4vO7Ksoj1Id5e+K94XUOzllqX1n47HEA50EKiXTCQbykxuJ4cYGIivjx/MRSTC5OA==", + "requires": { + "@apidevtools/json-schema-ref-parser": "^8.0.0", + "@apidevtools/openapi-schemas": "^2.0.2", + "@apidevtools/swagger-methods": "^3.0.0", + "@jsdevtools/ono": "^7.1.0", + "call-me-maybe": "^1.0.1", + "openapi-types": "^1.3.5", + "z-schema": "^4.2.2" + } + }, "@babel/code-frame": { - "version": "7.5.5", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.5.5.tgz", - "integrity": "sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw==", + "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/core": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.9.0.tgz", + "integrity": "sha512-kWc7L0fw1xwvI0zi8OKVBuxRVefwGOrKSQMvrQ3dW+bIIavBY3/NpXmpjMy7bQnLgwgzWQZ8TlM57YHpHNHz4w==", "dev": true, "requires": { - "@babel/highlight": "^7.0.0" + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.0", + "@babel/helper-module-transforms": "^7.9.0", + "@babel/helpers": "^7.9.0", + "@babel/parser": "^7.9.0", + "@babel/template": "^7.8.6", + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.1", + "json5": "^2.1.2", + "lodash": "^4.17.13", + "resolve": "^1.3.2", + "semver": "^5.4.1", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "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 + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } } }, "@babel/generator": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.7.4.tgz", - "integrity": "sha512-m5qo2WgdOJeyYngKImbkyQrnUN1mPceaG5BV+G0E3gWsa4l/jCSryWJdM2x8OuGAOyh+3d5pVYfZWCiNFtynxg==", + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.9.5.tgz", + "integrity": "sha512-GbNIxVB3ZJe3tLeDm1HSn2AhuD/mVcyLDpgtLXa5tplmWrJdF/elxB56XNqCuD6szyNkDi6wuoKXln3QeBmCHQ==", "dev": true, "requires": { - "@babel/types": "^7.7.4", + "@babel/types": "^7.9.5", "jsesc": "^2.5.1", "lodash": "^4.17.13", "source-map": "^0.5.0" @@ -34,42 +124,123 @@ } }, "@babel/helper-function-name": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz", - "integrity": "sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ==", + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.9.5.tgz", + "integrity": "sha512-JVcQZeXM59Cd1qanDUxv9fgJpt3NeKUaqBqUEvfmQ+BCOKq2xUgaWZW2hr0dkbyJgezYuplEoh5knmrnS68efw==", "dev": true, "requires": { - "@babel/helper-get-function-arity": "^7.7.4", - "@babel/template": "^7.7.4", - "@babel/types": "^7.7.4" + "@babel/helper-get-function-arity": "^7.8.3", + "@babel/template": "^7.8.3", + "@babel/types": "^7.9.5" } }, "@babel/helper-get-function-arity": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz", - "integrity": "sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz", + "integrity": "sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz", + "integrity": "sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-imports": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz", + "integrity": "sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg==", + "dev": true, + "requires": { + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-module-transforms": { + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.9.0.tgz", + "integrity": "sha512-0FvKyu0gpPfIQ8EkxlrAydOWROdHpBmiCiRwLkUiBGhCUPRRbVD2/tm3sFr/c/GWFrQ/ffutGUAnx7V0FzT2wA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.8.3", + "@babel/helper-replace-supers": "^7.8.6", + "@babel/helper-simple-access": "^7.8.3", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/template": "^7.8.6", + "@babel/types": "^7.9.0", + "lodash": "^4.17.13" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz", + "integrity": "sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ==", "dev": true, "requires": { - "@babel/types": "^7.7.4" + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-replace-supers": { + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.8.6.tgz", + "integrity": "sha512-PeMArdA4Sv/Wf4zXwBKPqVj7n9UF/xg6slNRtZW84FM7JpE1CbG8B612FyM4cxrf4fMAMGO0kR7voy1ForHHFA==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.8.3", + "@babel/helper-optimise-call-expression": "^7.8.3", + "@babel/traverse": "^7.8.6", + "@babel/types": "^7.8.6" + } + }, + "@babel/helper-simple-access": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz", + "integrity": "sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/types": "^7.8.3" } }, "@babel/helper-split-export-declaration": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz", - "integrity": "sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug==", + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz", + "integrity": "sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA==", "dev": true, "requires": { - "@babel/types": "^7.7.4" + "@babel/types": "^7.8.3" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", + "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", + "dev": true + }, + "@babel/helpers": { + "version": "7.9.2", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.9.2.tgz", + "integrity": "sha512-JwLvzlXVPjO8eU9c/wF9/zOIN7X6h8DYf7mG4CiFRZRvZNKEF5dQ3H3V+ASkHoIB3mWhatgl5ONhyqHRI6MppA==", + "dev": true, + "requires": { + "@babel/template": "^7.8.3", + "@babel/traverse": "^7.9.0", + "@babel/types": "^7.9.0" } }, "@babel/highlight": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.5.0.tgz", - "integrity": "sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ==", + "version": "7.9.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", + "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", "dev": true, "requires": { + "@babel/helper-validator-identifier": "^7.9.0", "chalk": "^2.0.0", - "esutils": "^2.0.2", "js-tokens": "^4.0.0" }, "dependencies": { @@ -105,34 +276,34 @@ } }, "@babel/parser": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.7.4.tgz", - "integrity": "sha512-jIwvLO0zCL+O/LmEJQjWA75MQTWwx3c3u2JOTDK5D3/9egrWRRA0/0hk9XXywYnXZVVpzrBYeIQTmhwUaePI9g==", + "version": "7.9.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.9.4.tgz", + "integrity": "sha512-bC49otXX6N0/VYhgOMh4gnP26E9xnDZK3TmbNpxYzzz9BQLBosQwfyOe9/cXUU3txYhTzLCbcqd5c8y/OmCjHA==", "dev": true }, "@babel/template": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.7.4.tgz", - "integrity": "sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw==", + "version": "7.8.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz", + "integrity": "sha512-zbMsPMy/v0PWFZEhQJ66bqjhH+z0JgMoBWuikXybgG3Gkd/3t5oQ1Rw2WQhnSrsOmsKXnZOx15tkC4qON/+JPg==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "@babel/parser": "^7.7.4", - "@babel/types": "^7.7.4" + "@babel/code-frame": "^7.8.3", + "@babel/parser": "^7.8.6", + "@babel/types": "^7.8.6" } }, "@babel/traverse": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.7.4.tgz", - "integrity": "sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw==", + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.9.5.tgz", + "integrity": "sha512-c4gH3jsvSuGUezlP6rzSJ6jf8fYjLj3hsMZRx/nX0h+fmHN0w+ekubRrHPqnMec0meycA2nwCsJ7dC8IPem2FQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.5.5", - "@babel/generator": "^7.7.4", - "@babel/helper-function-name": "^7.7.4", - "@babel/helper-split-export-declaration": "^7.7.4", - "@babel/parser": "^7.7.4", - "@babel/types": "^7.7.4", + "@babel/code-frame": "^7.8.3", + "@babel/generator": "^7.9.5", + "@babel/helper-function-name": "^7.9.5", + "@babel/helper-split-export-declaration": "^7.8.3", + "@babel/parser": "^7.9.0", + "@babel/types": "^7.9.5", "debug": "^4.1.0", "globals": "^11.1.0", "lodash": "^4.17.13" @@ -156,21 +327,123 @@ } }, "@babel/types": { - "version": "7.7.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.7.4.tgz", - "integrity": "sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA==", + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.9.5.tgz", + "integrity": "sha512-XjnvNqenk818r5zMaba+sLQjnbda31UfUURv3ei0qPQw4u+j2jMyJ5b11y8ZHYTRSI3NnInQkkkRT4fLqqPdHg==", "dev": true, "requires": { - "esutils": "^2.0.2", + "@babel/helper-validator-identifier": "^7.9.5", "lodash": "^4.17.13", "to-fast-properties": "^2.0.0" } }, - "abab": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/abab/-/abab-1.0.4.tgz", - "integrity": "sha1-X6rZwsB/YN12dw9xzwJbYqY8/U4=", - "optional": true + "@istanbuljs/load-nyc-config": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.0.0.tgz", + "integrity": "sha512-ZR0rq/f/E4f4XcgnDvtMWXCUJpi8eO0rssVhmztsZqLIEFA9UUP9zmpE0VxlM+kv/E1ul2I876Fwil2ayptDVg==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + } + } + }, + "@istanbuljs/schema": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", + "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "dev": true + }, + "@jsdevtools/ono": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.2.tgz", + "integrity": "sha512-qS/a24RA5FEoiJS9wiv6Pwg2c/kiUo3IVUQcfeM9JvsR6pM8Yx+yl/6xWYLckZCT5jpLNhslgjiA8p/XcGyMRQ==" + }, + "@types/caseless": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz", + "integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w==" + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "@types/long": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.1.tgz", + "integrity": "sha512-5tXH6Bx/kNGd3MgffdmP4dy2Z+G4eaXw0SE81Tq3BNadtnMR5/ySMzX4SLEzHJzSmPNn4HIdpQsBvXMUykr58w==" + }, + "@types/node": { + "version": "13.13.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.4.tgz", + "integrity": "sha512-x26ur3dSXgv5AwKS0lNfbjpCakGIduWU1DU91Zz58ONRWrIKGunmZBNv4P7N+e27sJkiGDsw/3fT4AtsqQBrBA==" + }, + "@types/request": { + "version": "2.48.4", + "resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.4.tgz", + "integrity": "sha512-W1t1MTKYR8PxICH+A4HgEIPuAC3sbljoEVfyZbeFJJDbr30guDspJri2XOaM2E+Un7ZjrihaDi7cf6fPa2tbgw==", + "requires": { + "@types/caseless": "*", + "@types/node": "*", + "@types/tough-cookie": "*", + "form-data": "^2.5.0" + }, + "dependencies": { + "form-data": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", + "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + } + } + }, + "@types/tough-cookie": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-4.0.0.tgz", + "integrity": "sha512-I99sngh224D0M7XgW1s120zxCt3VYQ3IQsuw3P3jbq5GG4yc79+ZjyKznyOGIQrflfylLgcfekeZW/vk0yng6A==" }, "accepts": { "version": "1.3.7", @@ -181,20 +454,10 @@ "negotiator": "0.6.2" } }, - "acorn": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", - "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", - "optional": true - }, - "acorn-globals": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", - "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=", - "optional": true, - "requires": { - "acorn": "^2.1.0" - } + "adm-zip": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.14.tgz", + "integrity": "sha512-/9aQCnQHF+0IiCl0qhXoK7qs//SwYE7zX8lsr/DNk1BRAHYxeLZPL4pguwK29gUEqasYQjqPtEpDRSWEkdHn9g==" }, "after": { "version": "0.8.2", @@ -209,31 +472,32 @@ "humanize-ms": "^1.2.1" } }, + "aggregate-error": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", + "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", + "dev": true, + "requires": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + } + }, "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", + "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", - "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + "ansi-colors": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", + "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", + "dev": true }, "ansi-regex": { "version": "2.1.1", @@ -245,13 +509,23 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, "append-transform": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-1.0.0.tgz", - "integrity": "sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", + "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", "dev": true, "requires": { - "default-require-extensions": "^2.0.0" + "default-require-extensions": "^3.0.0" } }, "archiver": { @@ -291,26 +565,6 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" } - }, - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "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" - } } } }, @@ -352,16 +606,10 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -400,7 +648,6 @@ "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, "requires": { "sprintf-js": "~1.0.2" } @@ -454,9 +701,9 @@ "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" }, "aws4": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" }, "backo2": { "version": "1.0.2", @@ -485,6 +732,11 @@ "resolved": "https://registry.npmjs.org/base64id/-/base64id-1.0.0.tgz", "integrity": "sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY=" }, + "bath-es5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/bath-es5/-/bath-es5-3.0.3.tgz", + "integrity": "sha512-PdCioDToH3t84lP40kUFCKWCOCH389Dl1kbC8FGoqOwamxsmqxxnJSXdkTOsPoNHXjem4+sJ+bbNoQm5zeCqxg==" + }, "bcrypt-pbkdf": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", @@ -502,9 +754,15 @@ } }, "bignumber.js": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-4.0.4.tgz", - "integrity": "sha512-LDXpJKVzEx2/OqNbG9mXBNvHuiRL4PzHCGfnANHMJ+fv68Ads3exDVJeGDJws+AoNEuca93bU3q+S0woeUaCdg==" + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "dev": true }, "binary-search": { "version": "1.3.6", @@ -512,34 +770,14 @@ "integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==" }, "bl": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-3.0.0.tgz", - "integrity": "sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.0.2.tgz", + "integrity": "sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ==", "dev": true, "requires": { - "readable-stream": "^3.0.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "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" - } - } + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, "blob": { @@ -569,10 +807,22 @@ "type-is": "~1.6.17" }, "dependencies": { - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" } } }, @@ -591,6 +841,15 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "browser-request": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/browser-request/-/browser-request-0.3.3.tgz", @@ -603,9 +862,9 @@ "dev": true }, "buffer": { - "version": "5.4.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.4.3.tgz", - "integrity": "sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", "dev": true, "requires": { "base64-js": "^1.0.2", @@ -619,9 +878,9 @@ "dev": true }, "buffer-writer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz", - "integrity": "sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" }, "bytes": { "version": "3.1.0", @@ -629,26 +888,32 @@ "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" }, "caching-transform": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-3.0.2.tgz", - "integrity": "sha512-Mtgcv3lh3U0zRii/6qVgQODdPA4G3zhG+jtbCWj39RXuUFTMzH0vcdMtaJS1jPowd+It2Pqr6y3NJMQqOqCE2w==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", + "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", "dev": true, "requires": { - "hasha": "^3.0.0", - "make-dir": "^2.0.0", - "package-hash": "^3.0.0", - "write-file-atomic": "^2.4.2" + "hasha": "^5.0.0", + "make-dir": "^3.0.0", + "package-hash": "^4.0.0", + "write-file-atomic": "^3.0.0" } }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=" + }, "callsite": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz", "integrity": "sha1-KAOY5dZkvXQDi28JBRU+borxvCA=" }, "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true }, "caseless": { "version": "0.12.0", @@ -656,23 +921,16 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "cassandra-driver": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/cassandra-driver/-/cassandra-driver-2.0.1.tgz", - "integrity": "sha1-BydZq4N2KNy8tbxngoPcySLHZ+I=", + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/cassandra-driver/-/cassandra-driver-4.5.1.tgz", + "integrity": "sha512-N5pxCxi9jPJzHuhx7ObClJtePcby8xuSb3mQkik1EE57CWqI7dEAuZZUaM7Flboasbwf/uSmw9oTfuf6sZMq9A==", "requires": { - "async": "^0.9.0", + "@types/long": "^4.0.0", + "@types/node": ">=8", + "adm-zip": "^0.4.13", "long": "^2.2.0" } }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", - "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" - } - }, "chalk": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", @@ -691,64 +949,114 @@ "integrity": "sha1-G+4yPt6hUrue8E9BvG5rD1lIqUE=" }, "cheerio": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz", - "integrity": "sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU=", + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz", + "integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=", "requires": { "css-select": "~1.2.0", "dom-serializer": "~0.1.0", "entities": "~1.1.1", - "htmlparser2": "~3.8.1", - "jsdom": "^7.0.2", - "lodash": "^4.1.0" + "htmlparser2": "^3.9.1", + "lodash.assignin": "^4.0.9", + "lodash.bind": "^4.1.4", + "lodash.defaults": "^4.0.1", + "lodash.filter": "^4.4.0", + "lodash.flatten": "^4.2.0", + "lodash.foreach": "^4.3.0", + "lodash.map": "^4.4.0", + "lodash.merge": "^4.4.0", + "lodash.pick": "^4.2.1", + "lodash.reduce": "^4.4.0", + "lodash.reject": "^4.4.0", + "lodash.some": "^4.4.0" + } + }, + "chokidar": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", + "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", + "dev": true, + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.1", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" } }, "clean-css": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.19.tgz", - "integrity": "sha1-wyqKE8o7gkYJsUMGpdp22Hk8eHQ=", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", "requires": { - "commander": "2.8.x", - "source-map": "0.4.x" - }, - "dependencies": { - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", - "requires": { - "amdefine": ">=0.0.4" - } - } + "source-map": "~0.6.0" } }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", - "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", - "wordwrap": "0.0.2" - } + "clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "dev": true }, - "cloudant-follow": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/cloudant-follow/-/cloudant-follow-0.17.0.tgz", - "integrity": "sha512-JQ1xvKAHh8rsnSVBjATLCjz/vQw1sWBGadxr2H69yFMwD7hShUGDwwEefdypaxroUJ/w6t1cSwilp/hRUxEW8w==", + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, "requires": { - "browser-request": "~0.3.0", - "debug": "^3.0.0", - "request": "^2.83.0" + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" }, "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "requires": { - "ms": "^2.1.1" - } + "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 + }, + "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, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.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" + } + } + } + }, + "cloudant-follow": { + "version": "0.18.2", + "resolved": "https://registry.npmjs.org/cloudant-follow/-/cloudant-follow-0.18.2.tgz", + "integrity": "sha512-qu/AmKxDqJds+UmT77+0NbM7Yab2K3w0qSeJRzsq5dRWJTEJdWeb+XpG4OpKuTE9RKOa/Awn2gR3TTnvNr3TeA==", + "requires": { + "browser-request": "~0.3.0", + "debug": "^4.0.1", + "request": "^2.88.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } }, "ms": { "version": "2.1.2", @@ -781,12 +1089,9 @@ } }, "commander": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", - "requires": { - "graceful-readlink": ">= 1.0.0" - } + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "commondir": { "version": "1.0.1", @@ -827,16 +1132,10 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -938,19 +1237,6 @@ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" }, - "cp-file": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-6.2.0.tgz", - "integrity": "sha512-fmvV4caBnofhPe8kOcitBwSn2f39QLjnAnGq3gO9dfd75mUytzKNZB1hde6QHunW2Rt+OwuBOMc3i1tNElbszA==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "make-dir": "^2.0.0", - "nested-error-stacks": "^2.0.0", - "pify": "^4.0.1", - "safe-buffer": "^5.0.1" - } - }, "crc": { "version": "3.8.0", "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", @@ -968,40 +1254,30 @@ "requires": { "crc": "^3.4.4", "readable-stream": "^3.4.0" + } + }, + "cross-spawn": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.2.tgz", + "integrity": "sha512-PD6G8QG3S4FK/XCGFbEQrDqO2AnMMsy0meR7lerlIOHAAbkuavGU/pOqprrlvfTNjvowivTeBsjebAL0NSoMxw==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "dependencies": { - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "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==", + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { - "safe-buffer": "~5.2.0" + "isexe": "^2.0.0" } } } }, - "cross-spawn": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", - "integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "which": "^1.2.9" - } - }, "css-select": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz", @@ -1018,21 +1294,6 @@ "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz", "integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==" }, - "cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "optional": true - }, - "cssstyle": { - "version": "0.2.37", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-0.2.37.tgz", - "integrity": "sha1-VBCXI0yyUTyDzu06zdwn/yeYfVQ=", - "optional": true, - "requires": { - "cssom": "0.3.x" - } - }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -1052,27 +1313,23 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" - }, - "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=", - "optional": true + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true }, "default-require-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-2.0.0.tgz", - "integrity": "sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", + "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", "dev": true, "requires": { - "strip-bom": "^3.0.0" + "strip-bom": "^4.0.0" } }, "define-properties": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -1082,6 +1339,11 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -1099,9 +1361,9 @@ "dev": true }, "dirty": { - "version": "0.9.9", - "resolved": "https://registry.npmjs.org/dirty/-/dirty-0.9.9.tgz", - "integrity": "sha1-94WATEz3kHIgyxD6V2siMp/tpUU=" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/dirty/-/dirty-1.1.0.tgz", + "integrity": "sha1-cO3SuZlUHcmXT9Ooy9DGcP4jYHg=" }, "dom-serializer": { "version": "0.1.1", @@ -1118,9 +1380,9 @@ "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" }, "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", "requires": { "domelementtype": "1" } @@ -1134,11 +1396,6 @@ "domelementtype": "1" } }, - "double-ended-queue": { - "version": "2.1.0-0", - "resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz", - "integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw=" - }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -1159,9 +1416,9 @@ "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" }, "elasticsearch": { - "version": "15.1.1", - "resolved": "https://registry.npmjs.org/elasticsearch/-/elasticsearch-15.1.1.tgz", - "integrity": "sha512-Yr9xy10rUMjDty7qCys7X9AIW5+PX4Gtv2NksZqXIc+AZiWna/y2QwZdiSLtb5LTOKDp7PbegfuokhIjMHUpKw==", + "version": "16.7.1", + "resolved": "https://registry.npmjs.org/elasticsearch/-/elasticsearch-16.7.1.tgz", + "integrity": "sha512-PL/BxB03VGbbghJwISYvVcrR9KbSSkuQ7OM//jHJg/End/uC2fvXg4QI7RXLvCGbhBuNQ8dPue7DOOPra73PCw==", "requires": { "agentkeepalive": "^3.4.1", "chalk": "^1.0.0", @@ -1256,41 +1513,35 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, "errs": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/errs/-/errs-0.3.2.tgz", "integrity": "sha1-eYCZstvTfKK8dJ5TinwTB9C1BJk=" }, "es-abstract": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.16.0.tgz", - "integrity": "sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg==", + "version": "1.17.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", + "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", + "dev": true, "requires": { - "es-to-primitive": "^1.2.0", + "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "has": "^1.0.3", - "has-symbols": "^1.0.0", - "is-callable": "^1.1.4", - "is-regex": "^1.0.4", - "object-inspect": "^1.6.0", + "has-symbols": "^1.0.1", + "is-callable": "^1.1.5", + "is-regex": "^1.0.5", + "object-inspect": "^1.7.0", "object-keys": "^1.1.1", - "string.prototype.trimleft": "^2.1.0", - "string.prototype.trimright": "^2.1.0" + "object.assign": "^4.1.0", + "string.prototype.trimleft": "^2.1.1", + "string.prototype.trimright": "^2.1.1" } }, "es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -1313,35 +1564,10 @@ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, - "escodegen": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.12.0.tgz", - "integrity": "sha512-TuA+EhsanGcme5T3R0L80u4t8CpbXQjegRmf7+FPTJrtCTErXFeelblRgHQa1FofEzqYYJmJ/OqjTwREp9qgmg==", - "optional": true, - "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" - } - }, "esprima": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", - "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", - "optional": true - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "optional": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==" + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "etag": { "version": "1.8.1", @@ -1400,11 +1626,6 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" }, - "qs": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" - }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -1412,6 +1633,11 @@ } } }, + "express-rate-limit": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-5.1.1.tgz", + "integrity": "sha512-puA1zcCx/quwWUOU6pT6daCt6t7SweD9wKChKhb+KSgFMKRwS81C224hiSAUANw/gnSHiwEhgozM/2ezEBZPeA==" + }, "express-session": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.0.tgz", @@ -1450,20 +1676,23 @@ "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" }, "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=" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" }, "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=" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "optional": true + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } }, "finalhandler": { "version": "1.1.2", @@ -1480,14 +1709,14 @@ } }, "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", "dev": true, "requires": { "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" } }, "find-root": { @@ -1504,14 +1733,23 @@ "locate-path": "^3.0.0" } }, + "flat": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", + "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", + "dev": true, + "requires": { + "is-buffer": "~2.0.3" + } + }, "foreground-child": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-1.5.6.tgz", - "integrity": "sha1-T9ca0t/elnibmApcCilZN8svXOk=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", + "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", "dev": true, "requires": { - "cross-spawn": "^4", - "signal-exit": "^3.0.0" + "cross-spawn": "^7.0.0", + "signal-exit": "^3.0.2" } }, "forever-agent": { @@ -1544,6 +1782,12 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, + "fromentries": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.0.tgz", + "integrity": "sha512-33X7H/wdfO99GdRLLgkjUrD4geAFdq/Uv0kl3HD4da6HDixd2GUg8Mw7dahLCV9r/EARkmtYBB6Tch4EEokFTQ==", + "dev": true + }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -1556,15 +1800,24 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "dev": true, + "optional": true + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true }, - "generic-pool": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.3.tgz", - "integrity": "sha1-eAw29p360FpaBF3Te+etyhGk9v8=" + "gensync": { + "version": "1.0.0-beta.1", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", + "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", + "dev": true }, "get-caller-file": { "version": "2.0.5", @@ -1581,9 +1834,9 @@ } }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -1594,6 +1847,15 @@ "path-is-absolute": "^1.0.0" } }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, "globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", @@ -1605,49 +1867,12 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" - }, "growl": { "version": "1.10.5", "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", "dev": true }, - "handlebars": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.5.3.tgz", - "integrity": "sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA==", - "dev": true, - "requires": { - "neo-async": "^2.6.0", - "optimist": "^0.6.1", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "optional": true - }, - "uglify-js": { - "version": "3.6.9", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.9.tgz", - "integrity": "sha512-pcnnhaoG6RtrvHJ1dFncAe8Od6Nuy30oaJ82ts6//sGSXOP5UjBMEthiProjXmMNHOfd93sqlkztifFMcb+4yw==", - "dev": true, - "optional": true, - "requires": { - "commander": "~2.20.3", - "source-map": "~0.6.1" - } - } - } - }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -1666,6 +1891,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -1707,65 +1933,54 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", + "dev": true }, "hasha": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-3.0.0.tgz", - "integrity": "sha1-UqMvq4Vp1BymmmH/GiFPjrfIvTk=", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", + "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", "dev": true, "requires": { - "is-stream": "^1.0.1" + "is-stream": "^2.0.0", + "type-fest": "^0.8.0" } }, "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "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==", + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", "dev": true }, "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", - "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - }, - "dependencies": { - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" - } + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz", + "integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==", + "requires": { + "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" } }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", "requires": { "depd": "~1.1.2", - "inherits": "2.0.3", + "inherits": "2.0.4", "setprototypeof": "1.1.1", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - } } }, "http-signature": { @@ -1806,6 +2021,12 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, "indexof": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", @@ -1827,30 +2048,42 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ipaddr.js": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz", - "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA==" + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } }, "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", + "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", + "dev": true }, "is-callable": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", + "dev": true }, "is-date-object": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", + "dev": true + }, + "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 }, "is-fullwidth-code-point": { "version": "2.0.0", @@ -1858,29 +2091,46 @@ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", "dev": true }, + "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, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "is-promise": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=" }, "is-regex": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", + "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", + "dev": true, "requires": { - "has": "^1.0.1" + "has": "^1.0.3" } }, "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", "dev": true }, "is-symbol": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -1890,6 +2140,12 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -1907,33 +2163,33 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" }, "istanbul-lib-coverage": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz", - "integrity": "sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", + "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", "dev": true }, "istanbul-lib-hook": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-2.0.7.tgz", - "integrity": "sha512-vrRztU9VRRFDyC+aklfLoeXyNdTfga2EI3udDGn4cZ6fpSXpHLV9X6CHvfoMCPtggg8zvDDmC4b9xfu0z6/llA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", + "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", "dev": true, "requires": { - "append-transform": "^1.0.0" + "append-transform": "^2.0.0" } }, "istanbul-lib-instrument": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz", - "integrity": "sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.1.tgz", + "integrity": "sha512-imIchxnodll7pvQBYOqUu88EufLCU56LMeFPZZM/fJZ1irYcYdqroaV+ACK1Ila8ls09iEYArp+nqyC6lW1Vfg==", "dev": true, "requires": { - "@babel/generator": "^7.4.0", - "@babel/parser": "^7.4.3", - "@babel/template": "^7.4.0", - "@babel/traverse": "^7.4.3", - "@babel/types": "^7.4.0", - "istanbul-lib-coverage": "^2.0.5", - "semver": "^6.0.0" + "@babel/core": "^7.7.5", + "@babel/parser": "^7.7.5", + "@babel/template": "^7.7.4", + "@babel/traverse": "^7.7.4", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" }, "dependencies": { "semver": { @@ -1944,38 +2200,57 @@ } } }, + "istanbul-lib-processinfo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", + "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "dev": true, + "requires": { + "archy": "^1.0.0", + "cross-spawn": "^7.0.0", + "istanbul-lib-coverage": "^3.0.0-alpha.1", + "make-dir": "^3.0.0", + "p-map": "^3.0.0", + "rimraf": "^3.0.0", + "uuid": "^3.3.3" + } + }, "istanbul-lib-report": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz", - "integrity": "sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", "dev": true, "requires": { - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "supports-color": "^6.1.0" + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" }, "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "supports-color": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", - "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" } } } }, "istanbul-lib-source-maps": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz", - "integrity": "sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", "dev": true, "requires": { "debug": "^4.1.1", - "istanbul-lib-coverage": "^2.0.5", - "make-dir": "^2.1.0", - "rimraf": "^2.6.3", + "istanbul-lib-coverage": "^3.0.0", "source-map": "^0.6.1" }, "dependencies": { @@ -1997,19 +2272,15 @@ } }, "istanbul-reports": { - "version": "2.2.6", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-2.2.6.tgz", - "integrity": "sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", "dev": true, "requires": { - "handlebars": "^4.1.2" + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" } }, - "js-string-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=" - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -2020,18 +2291,9 @@ "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, "requires": { "argparse": "^1.0.7", "esprima": "^4.0.0" - }, - "dependencies": { - "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 - } } }, "jsbn": { @@ -2039,41 +2301,12 @@ "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" }, - "jsdom": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-7.2.2.tgz", - "integrity": "sha1-QLQCdwwr2iNGkJa+6Rq2deOx/G4=", - "optional": true, - "requires": { - "abab": "^1.0.0", - "acorn": "^2.4.0", - "acorn-globals": "^1.0.4", - "cssom": ">= 0.3.0 < 0.4.0", - "cssstyle": ">= 0.2.29 < 0.3.0", - "escodegen": "^1.6.1", - "nwmatcher": ">= 1.3.7 < 2.0.0", - "parse5": "^1.5.1", - "request": "^2.55.0", - "sax": "^1.1.4", - "symbol-tree": ">= 3.1.0 < 4.0.0", - "tough-cookie": "^2.2.0", - "webidl-conversions": "^2.0.0", - "whatwg-url-compat": "~0.6.5", - "xml-name-validator": ">= 2.0.1 < 3.0.0" - } - }, "jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, - "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 - }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -2089,11 +2322,30 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "json5": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", + "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, "jsonminify": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/jsonminify/-/jsonminify-0.4.1.tgz", "integrity": "sha1-gF2vuzk5UYjO6atYLIHvlZ1+cQw=" }, + "jsonschema": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", + "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" + }, + "jsonschema-draft4": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/jsonschema-draft4/-/jsonschema-draft4-1.0.0.tgz", + "integrity": "sha1-8K8gBQVPDwrefqIRhhS2ncUS2GU=" + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -2105,24 +2357,11 @@ "verror": "1.10.0" } }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "requires": { - "is-buffer": "^1.1.5" - } - }, "languages4translatewiki": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/languages4translatewiki/-/languages4translatewiki-0.1.3.tgz", "integrity": "sha1-xDYgbgUtIUkLEQF6RNURj5Ih5ds=" }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" - }, "lazystream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", @@ -2138,16 +2377,10 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -2176,36 +2409,6 @@ } } }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "optional": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "load-json-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", - "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, "locate-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", @@ -2221,11 +2424,25 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==" }, + "lodash.assignin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz", + "integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI=" + }, + "lodash.bind": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz", + "integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU=" + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + }, "lodash.defaults": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=", - "dev": true + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" }, "lodash.difference": { "version": "4.5.0", @@ -2233,11 +2450,15 @@ "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=", "dev": true }, + "lodash.filter": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz", + "integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4=" + }, "lodash.flatten": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=", - "dev": true + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" }, "lodash.flattendeep": { "version": "4.4.0", @@ -2245,10 +2466,20 @@ "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", "dev": true }, - "lodash.isempty": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", - "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=" + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" }, "lodash.isplainobject": { "version": "4.0.6", @@ -2256,12 +2487,82 @@ "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", "dev": true }, + "lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=" + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==" + }, + "lodash.pick": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz", + "integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM=" + }, + "lodash.reduce": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz", + "integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs=" + }, + "lodash.reject": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz", + "integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU=" + }, + "lodash.some": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz", + "integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0=" + }, "lodash.union": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=", "dev": true }, + "log-symbols": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", + "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2" + }, + "dependencies": { + "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, + "requires": { + "color-convert": "^1.9.0" + } + }, + "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, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "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, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "log4js": { "version": "0.6.35", "resolved": "https://registry.npmjs.org/log4js/-/log4js-0.6.35.tgz", @@ -2286,6 +2587,11 @@ "version": "4.3.6", "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" } } }, @@ -2294,29 +2600,21 @@ "resolved": "https://registry.npmjs.org/long/-/long-2.4.0.tgz", "integrity": "sha1-n6GAux2VAM3CnEFWdmoZleH0Uk8=" }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } } }, "measured-core": { @@ -2338,15 +2636,6 @@ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" }, - "merge-source-map": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", - "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - } - }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -2358,16 +2647,16 @@ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" }, "mime-db": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", - "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==" + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" }, "mime-types": { - "version": "2.1.25", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", - "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", "requires": { - "mime-db": "1.42.0" + "mime-db": "1.44.0" } }, "minimatch": { @@ -2380,58 +2669,71 @@ } }, "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", "dev": true }, "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.3.tgz", + "integrity": "sha512-P+2gwrFqx8lhew375MQHHeTlY8AuOJSrGf0R5ddkEndUkmwpgUob/vQuBD1V22/Cw1/lJr4x+EjllSezBThzBg==", "dev": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" } }, "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.1.1.tgz", + "integrity": "sha512-3qQsu3ijNS3GkWcccT5Zw0hf/rWvu1fTN9sPvEd81hlwsr30GX2GcDSSoBxo24IR8FelmrAydGC6/1J5QQP4WA==", "dev": true, "requires": { + "ansi-colors": "3.2.3", "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", + "chokidar": "3.3.0", + "debug": "3.2.6", "diff": "3.5.0", "escape-string-regexp": "1.0.5", - "glob": "7.1.2", + "find-up": "3.0.0", + "glob": "7.1.3", "growl": "1.10.5", - "he": "1.1.1", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" + "mkdirp": "0.5.3", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" }, "dependencies": { - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "^2.1.1" } }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", + "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", "dev": true, "requires": { "has-flag": "^3.0.0" @@ -2439,20 +2741,29 @@ } } }, + "mock-json-schema": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/mock-json-schema/-/mock-json-schema-1.0.8.tgz", + "integrity": "sha512-22yL+WggSo8HXqw0HkXgXXJjJMSBCfv54htfwN4BabaFdJ3808jL0CzE+VaBRlj8Nr0+pnSVE9YvsDG5Quu6hQ==", + "requires": { + "lodash": "^4.17.11", + "openapi-types": "^1.3.2" + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, "mysql": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.15.0.tgz", - "integrity": "sha512-C7tjzWtbN5nzkLIV+E8Crnl9bFyc7d3XJcBAvHKEVkjrYjogz3llo22q6s/hw+UcsE4/844pDob9ac+3dVjQSA==", - "requires": { - "bignumber.js": "4.0.4", - "readable-stream": "2.3.3", - "safe-buffer": "5.1.1", - "sqlstring": "2.3.0" + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "requires": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" }, "dependencies": { "isarray": { @@ -2461,28 +2772,28 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", - "process-nextick-args": "~1.0.6", + "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", + "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { "safe-buffer": "~5.1.0" } @@ -2490,15 +2801,30 @@ } }, "nano": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/nano/-/nano-6.4.4.tgz", - "integrity": "sha512-7sldMrZI1ZH8QE29PnzohxLfR67WNVzMKLa7EMl3x9Hr+0G+YpOUCq50qZ9G66APrjcb0Of2BTOZLNBCutZGag==", + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/nano/-/nano-8.2.2.tgz", + "integrity": "sha512-1/rAvpd1J0Os0SazgutWQBx2buAq3KwJpmdIylPDqOwy73iQeAhTSCq3uzbGzvcNNW16Vv/BLXkk+DYcdcH+aw==", "requires": { - "cloudant-follow": "~0.17.0", - "debug": "^2.2.0", + "@types/request": "^2.48.4", + "cloudant-follow": "^0.18.2", + "debug": "^4.1.1", "errs": "^0.3.2", - "lodash.isempty": "^4.4.0", - "request": "^2.85.0" + "request": "^2.88.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } } }, "negotiator": { @@ -2506,17 +2832,32 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" }, - "neo-async": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.1.tgz", - "integrity": "sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw==", - "dev": true + "node-environment-flags": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", + "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", + "dev": true, + "requires": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } }, - "nested-error-stacks": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz", - "integrity": "sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==", - "dev": true + "node-preload": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", + "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", + "dev": true, + "requires": { + "process-on-spawn": "^1.0.0" + } }, "nodeify": { "version": "1.0.1", @@ -2527,29 +2868,6 @@ "promise": "~1.3.0" } }, - "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, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "resolve": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.2.tgz", - "integrity": "sha512-cAVTI2VLHWYsGOirfeYVVQ7ZDejtQ9fp4YhYckWDEkFfqbVjaT11iM8k6xSAfGFMM+gDpZjMnFssPu8we+mqFw==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - } - } - }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -2557,9 +2875,9 @@ "dev": true }, "npm": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/npm/-/npm-6.13.1.tgz", - "integrity": "sha512-2awiDZ9JuV/UoF4oXGhekCURC2X+eLLRz9/e58AGrPDlpzyn7e4oCaZmkzyEaisxM7jSoFKNnZhzB4xbmbM0Yw==", + "version": "6.14.4", + "resolved": "https://registry.npmjs.org/npm/-/npm-6.14.4.tgz", + "integrity": "sha512-B8UDDbWvdkW6RgXFn8/h2cHJP/u/FPa4HWeGzW23aNEBARN3QPrRaHqPIZW2NSN3fW649gtgUDNZpaRs0zTMPw==", "requires": { "JSONStream": "^1.3.5", "abbrev": "~1.1.1", @@ -2567,12 +2885,12 @@ "ansistyles": "~0.1.3", "aproba": "^2.0.0", "archy": "~1.0.0", - "bin-links": "^1.1.3", + "bin-links": "^1.1.7", "bluebird": "^3.5.5", "byte-size": "^5.0.1", "cacache": "^12.0.3", "call-limit": "^1.1.1", - "chownr": "^1.1.3", + "chownr": "^1.1.4", "ci-info": "^2.0.0", "cli-columns": "^3.1.2", "cli-table3": "^0.5.1", @@ -2588,11 +2906,11 @@ "find-npm-prefix": "^1.0.2", "fs-vacuum": "~1.2.10", "fs-write-stream-atomic": "~1.0.10", - "gentle-fs": "^2.2.1", - "glob": "^7.1.4", + "gentle-fs": "^2.3.0", + "glob": "^7.1.6", "graceful-fs": "^4.2.3", "has-unicode": "~2.0.1", - "hosted-git-info": "^2.8.5", + "hosted-git-info": "^2.8.8", "iferr": "^1.0.2", "imurmurhash": "*", "infer-owner": "^1.0.4", @@ -2610,7 +2928,7 @@ "libnpmorg": "^1.0.1", "libnpmsearch": "^2.0.2", "libnpmteam": "^1.0.2", - "libnpx": "^10.2.0", + "libnpx": "^10.2.2", "lock-verify": "^2.1.0", "lockfile": "^1.0.4", "lodash._baseindexof": "*", @@ -2627,9 +2945,9 @@ "lru-cache": "^5.1.1", "meant": "~1.0.1", "mississippi": "^3.0.0", - "mkdirp": "~0.5.1", + "mkdirp": "^0.5.4", "move-concurrently": "^1.0.1", - "node-gyp": "^5.0.5", + "node-gyp": "^5.1.0", "nopt": "~4.0.1", "normalize-package-data": "^2.5.0", "npm-audit-report": "^1.3.2", @@ -2637,16 +2955,16 @@ "npm-install-checks": "^3.0.2", "npm-lifecycle": "^3.1.4", "npm-package-arg": "^6.1.1", - "npm-packlist": "^1.4.6", + "npm-packlist": "^1.4.8", "npm-pick-manifest": "^3.0.2", - "npm-profile": "^4.0.2", - "npm-registry-fetch": "^4.0.2", + "npm-profile": "^4.0.4", + "npm-registry-fetch": "^4.0.3", "npm-user-validate": "~1.0.0", "npmlog": "~4.1.2", "once": "~1.4.0", "opener": "^1.5.1", "osenv": "^0.1.5", - "pacote": "^9.5.9", + "pacote": "^9.5.12", "path-is-inside": "~1.0.2", "promise-inflight": "~1.0.1", "qrcode-terminal": "^0.12.0", @@ -2655,13 +2973,13 @@ "read": "~1.0.7", "read-cmd-shim": "^1.0.5", "read-installed": "~4.0.3", - "read-package-json": "^2.1.0", + "read-package-json": "^2.1.1", "read-package-tree": "^5.3.1", - "readable-stream": "^3.4.0", + "readable-stream": "^3.6.0", "readdir-scoped-modules": "^1.1.0", "request": "^2.88.0", "retry": "^0.12.0", - "rimraf": "^2.6.3", + "rimraf": "^2.7.1", "safe-buffer": "^5.1.2", "semver": "^5.7.1", "sha": "^3.0.0", @@ -2688,8 +3006,7 @@ "dependencies": { "JSONStream": { "version": "1.3.5", - "resolved": false, - "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "bundled": true, "requires": { "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" @@ -2697,29 +3014,25 @@ }, "abbrev": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + "bundled": true }, "agent-base": { "version": "4.3.0", - "resolved": false, - "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==", + "bundled": true, "requires": { "es6-promisify": "^5.0.0" } }, "agentkeepalive": { "version": "3.5.2", - "resolved": false, - "integrity": "sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ==", + "bundled": true, "requires": { "humanize-ms": "^1.2.1" } }, "ajv": { "version": "5.5.2", - "resolved": false, - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "bundled": true, "requires": { "co": "^4.6.0", "fast-deep-equal": "^1.0.0", @@ -2729,49 +3042,41 @@ }, "ansi-align": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "bundled": true, "requires": { "string-width": "^2.0.0" } }, "ansi-regex": { "version": "2.1.1", - "resolved": false, - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "bundled": true }, "ansi-styles": { "version": "3.2.1", - "resolved": false, - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "bundled": true, "requires": { "color-convert": "^1.9.0" } }, "ansicolors": { "version": "0.3.2", - "resolved": false, - "integrity": "sha1-ZlWX3oap/+Oqm/vmyuXG6kJrSXk=" + "bundled": true }, "ansistyles": { "version": "0.1.3", - "resolved": false, - "integrity": "sha1-XeYEFb2gcbs3EnhUyGT0GyMlRTk=" + "bundled": true }, "aproba": { "version": "2.0.0", - "resolved": false, - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + "bundled": true }, "archy": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + "bundled": true }, "are-we-there-yet": { "version": "1.1.4", - "resolved": false, - "integrity": "sha1-u13KOCu5TwXhUZQ3PRb9O6HKEQ0=", + "bundled": true, "requires": { "delegates": "^1.0.0", "readable-stream": "^2.0.6" @@ -2779,8 +3084,7 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -2793,8 +3097,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "requires": { "safe-buffer": "~5.1.0" } @@ -2803,72 +3106,62 @@ }, "asap": { "version": "2.0.6", - "resolved": false, - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" + "bundled": true }, "asn1": { "version": "0.2.4", - "resolved": false, - "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "bundled": true, "requires": { "safer-buffer": "~2.1.0" } }, "assert-plus": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "bundled": true }, "asynckit": { "version": "0.4.0", - "resolved": false, - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + "bundled": true }, "aws-sign2": { "version": "0.7.0", - "resolved": false, - "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + "bundled": true }, "aws4": { "version": "1.8.0", - "resolved": false, - "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + "bundled": true }, "balanced-match": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + "bundled": true }, "bcrypt-pbkdf": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "bundled": true, "optional": true, "requires": { "tweetnacl": "^0.14.3" } }, "bin-links": { - "version": "1.1.3", - "resolved": false, - "integrity": "sha512-TEwmH4PHU/D009stP+fkkazMJgkBNCv60z01lQ/Mn8E6+ThHoD03svMnBVuCowwXo2nP2qKyKZxKxp58OHRzxw==", + "version": "1.1.7", + "bundled": true, "requires": { "bluebird": "^3.5.3", "cmd-shim": "^3.0.0", - "gentle-fs": "^2.0.1", + "gentle-fs": "^2.3.0", "graceful-fs": "^4.1.15", + "npm-normalize-package-bin": "^1.0.0", "write-file-atomic": "^2.3.0" } }, "bluebird": { "version": "3.5.5", - "resolved": false, - "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w==" + "bundled": true }, "boxen": { "version": "1.3.0", - "resolved": false, - "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "bundled": true, "requires": { "ansi-align": "^2.0.0", "camelcase": "^4.0.0", @@ -2881,8 +3174,7 @@ }, "brace-expansion": { "version": "1.1.11", - "resolved": false, - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "bundled": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2890,28 +3182,23 @@ }, "buffer-from": { "version": "1.0.0", - "resolved": false, - "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==" + "bundled": true }, "builtins": { "version": "1.0.3", - "resolved": false, - "integrity": "sha1-y5T662HIaWRR2zZTThQi+U8K7og=" + "bundled": true }, "byline": { "version": "5.0.0", - "resolved": false, - "integrity": "sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE=" + "bundled": true }, "byte-size": { "version": "5.0.1", - "resolved": false, - "integrity": "sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw==" + "bundled": true }, "cacache": { "version": "12.0.3", - "resolved": false, - "integrity": "sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw==", + "bundled": true, "requires": { "bluebird": "^3.5.5", "chownr": "^1.1.1", @@ -2932,28 +3219,23 @@ }, "call-limit": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-5twvci5b9eRBw2wCfPtN0GmlR2/gadZqyFpPhOK6CvMFoFgA+USnZ6Jpu1lhG9h85pQ3Ouil3PfXWRD4EUaRiQ==" + "bundled": true }, "camelcase": { "version": "4.1.0", - "resolved": false, - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + "bundled": true }, "capture-stack-trace": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=" + "bundled": true }, "caseless": { "version": "0.12.0", - "resolved": false, - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + "bundled": true }, "chalk": { "version": "2.4.1", - "resolved": false, - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "bundled": true, "requires": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -2961,32 +3243,27 @@ } }, "chownr": { - "version": "1.1.3", - "resolved": false, - "integrity": "sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw==" + "version": "1.1.4", + "bundled": true }, "ci-info": { "version": "2.0.0", - "resolved": false, - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + "bundled": true }, "cidr-regex": { "version": "2.0.10", - "resolved": false, - "integrity": "sha512-sB3ogMQXWvreNPbJUZMRApxuRYd+KoIo4RGQ81VatjmMW6WJPo+IJZ2846FGItr9VzKo5w7DXzijPLGtSd0N3Q==", + "bundled": true, "requires": { "ip-regex": "^2.1.0" } }, "cli-boxes": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=" + "bundled": true }, "cli-columns": { "version": "3.1.2", - "resolved": false, - "integrity": "sha1-ZzLZcpee/CrkRKHwjgj6E5yWoY4=", + "bundled": true, "requires": { "string-width": "^2.0.0", "strip-ansi": "^3.0.1" @@ -2994,8 +3271,7 @@ }, "cli-table3": { "version": "0.5.1", - "resolved": false, - "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", + "bundled": true, "requires": { "colors": "^1.1.2", "object-assign": "^4.1.0", @@ -3004,8 +3280,7 @@ }, "cliui": { "version": "4.1.0", - "resolved": false, - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "bundled": true, "requires": { "string-width": "^2.1.1", "strip-ansi": "^4.0.0", @@ -3014,13 +3289,11 @@ "dependencies": { "ansi-regex": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "bundled": true }, "strip-ansi": { "version": "4.0.0", - "resolved": false, - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "bundled": true, "requires": { "ansi-regex": "^3.0.0" } @@ -3029,13 +3302,11 @@ }, "clone": { "version": "1.0.4", - "resolved": false, - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + "bundled": true }, "cmd-shim": { "version": "3.0.3", - "resolved": false, - "integrity": "sha512-DtGg+0xiFhQIntSBRzL2fRQBnmtAVwXIDo4Qq46HPpObYquxMaZS4sb82U9nH91qJrlosC1wa9gwr0QyL/HypA==", + "bundled": true, "requires": { "graceful-fs": "^4.1.2", "mkdirp": "~0.5.0" @@ -3043,37 +3314,31 @@ }, "co": { "version": "4.6.0", - "resolved": false, - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + "bundled": true }, "code-point-at": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + "bundled": true }, "color-convert": { "version": "1.9.1", - "resolved": false, - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "bundled": true, "requires": { "color-name": "^1.1.1" } }, "color-name": { "version": "1.1.3", - "resolved": false, - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "bundled": true }, "colors": { "version": "1.3.3", - "resolved": false, - "integrity": "sha512-mmGt/1pZqYRjMxB1axhTo16/snVZ5krrKkcmMeVKxzECMMXoCgnvTPp10QgHfcbQZw8Dq2jMNG6je4JlWU0gWg==", + "bundled": true, "optional": true }, "columnify": { "version": "1.5.4", - "resolved": false, - "integrity": "sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs=", + "bundled": true, "requires": { "strip-ansi": "^3.0.0", "wcwidth": "^1.0.0" @@ -3081,21 +3346,18 @@ }, "combined-stream": { "version": "1.0.6", - "resolved": false, - "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", + "bundled": true, "requires": { "delayed-stream": "~1.0.0" } }, "concat-map": { "version": "0.0.1", - "resolved": false, - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "bundled": true }, "concat-stream": { "version": "1.6.2", - "resolved": false, - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "bundled": true, "requires": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -3105,8 +3367,7 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3119,8 +3380,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "requires": { "safe-buffer": "~5.1.0" } @@ -3129,8 +3389,7 @@ }, "config-chain": { "version": "1.1.12", - "resolved": false, - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "bundled": true, "requires": { "ini": "^1.3.4", "proto-list": "~1.2.1" @@ -3138,8 +3397,7 @@ }, "configstore": { "version": "3.1.2", - "resolved": false, - "integrity": "sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw==", + "bundled": true, "requires": { "dot-prop": "^4.1.0", "graceful-fs": "^4.1.2", @@ -3151,13 +3409,11 @@ }, "console-control-strings": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + "bundled": true }, "copy-concurrently": { "version": "1.0.5", - "resolved": false, - "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "bundled": true, "requires": { "aproba": "^1.1.1", "fs-write-stream-atomic": "^1.0.8", @@ -3169,33 +3425,28 @@ "dependencies": { "aproba": { "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "bundled": true }, "iferr": { "version": "0.1.5", - "resolved": false, - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + "bundled": true } } }, "core-util-is": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "bundled": true }, "create-error-class": { "version": "3.0.2", - "resolved": false, - "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "bundled": true, "requires": { "capture-stack-trace": "^1.0.0" } }, "cross-spawn": { "version": "5.1.0", - "resolved": false, - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "bundled": true, "requires": { "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", @@ -3204,8 +3455,7 @@ "dependencies": { "lru-cache": { "version": "4.1.5", - "resolved": false, - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "bundled": true, "requires": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" @@ -3213,104 +3463,87 @@ }, "yallist": { "version": "2.1.2", - "resolved": false, - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + "bundled": true } } }, "crypto-random-string": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4=" + "bundled": true }, "cyclist": { "version": "0.2.2", - "resolved": false, - "integrity": "sha1-GzN5LhHpFKL9bW7WRHRkRE5fpkA=" + "bundled": true }, "dashdash": { "version": "1.14.1", - "resolved": false, - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "bundled": true, "requires": { "assert-plus": "^1.0.0" } }, "debug": { "version": "3.1.0", - "resolved": false, - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "bundled": true, "requires": { "ms": "2.0.0" }, "dependencies": { "ms": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "bundled": true } } }, "debuglog": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI=" + "bundled": true }, "decamelize": { "version": "1.2.0", - "resolved": false, - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "bundled": true }, "decode-uri-component": { "version": "0.2.0", - "resolved": false, - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=" + "bundled": true }, "deep-extend": { - "version": "0.5.1", - "resolved": false, - "integrity": "sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w==" + "version": "0.6.0", + "bundled": true }, "defaults": { "version": "1.0.3", - "resolved": false, - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "bundled": true, "requires": { "clone": "^1.0.2" } }, "define-properties": { "version": "1.1.3", - "resolved": false, - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "bundled": true, "requires": { "object-keys": "^1.0.12" } }, "delayed-stream": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + "bundled": true }, "delegates": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + "bundled": true }, "detect-indent": { "version": "5.0.0", - "resolved": false, - "integrity": "sha1-OHHMCmoALow+Wzz38zYmRnXwa50=" + "bundled": true }, "detect-newline": { "version": "2.1.0", - "resolved": false, - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=" + "bundled": true }, "dezalgo": { "version": "1.0.3", - "resolved": false, - "integrity": "sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY=", + "bundled": true, "requires": { "asap": "^2.0.0", "wrappy": "1" @@ -3318,26 +3551,22 @@ }, "dot-prop": { "version": "4.2.0", - "resolved": false, - "integrity": "sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==", + "bundled": true, "requires": { "is-obj": "^1.0.0" } }, "dotenv": { "version": "5.0.1", - "resolved": false, - "integrity": "sha512-4As8uPrjfwb7VXC+WnLCbXK7y+Ueb2B3zgNCePYfhxS1PYeaO1YTeplffTEcbfLhvFNGLAz90VvJs9yomG7bow==" + "bundled": true }, "duplexer3": { "version": "0.1.4", - "resolved": false, - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + "bundled": true }, "duplexify": { "version": "3.6.0", - "resolved": false, - "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", + "bundled": true, "requires": { "end-of-stream": "^1.0.0", "inherits": "^2.0.1", @@ -3347,8 +3576,7 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3361,8 +3589,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "requires": { "safe-buffer": "~5.1.0" } @@ -3371,8 +3598,7 @@ }, "ecc-jsbn": { "version": "0.1.2", - "resolved": false, - "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "bundled": true, "optional": true, "requires": { "jsbn": "~0.1.0", @@ -3381,47 +3607,40 @@ }, "editor": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-YMf4e9YrzGqJT6jM1q+3gjok90I=" + "bundled": true }, "encoding": { "version": "0.1.12", - "resolved": false, - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "bundled": true, "requires": { "iconv-lite": "~0.4.13" } }, "end-of-stream": { "version": "1.4.1", - "resolved": false, - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "bundled": true, "requires": { "once": "^1.4.0" } }, "env-paths": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=" + "version": "2.2.0", + "bundled": true }, "err-code": { "version": "1.1.2", - "resolved": false, - "integrity": "sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA=" + "bundled": true }, "errno": { "version": "0.1.7", - "resolved": false, - "integrity": "sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg==", + "bundled": true, "requires": { "prr": "~1.0.1" } }, "es-abstract": { "version": "1.12.0", - "resolved": false, - "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "bundled": true, "requires": { "es-to-primitive": "^1.1.1", "function-bind": "^1.1.1", @@ -3432,8 +3651,7 @@ }, "es-to-primitive": { "version": "1.2.0", - "resolved": false, - "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==", + "bundled": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -3442,26 +3660,22 @@ }, "es6-promise": { "version": "4.2.8", - "resolved": false, - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" + "bundled": true }, "es6-promisify": { "version": "5.0.0", - "resolved": false, - "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=", + "bundled": true, "requires": { "es6-promise": "^4.0.3" } }, "escape-string-regexp": { "version": "1.0.5", - "resolved": false, - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + "bundled": true }, "execa": { "version": "0.7.0", - "resolved": false, - "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "bundled": true, "requires": { "cross-spawn": "^5.0.1", "get-stream": "^3.0.0", @@ -3474,53 +3688,44 @@ "dependencies": { "get-stream": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + "bundled": true } } }, "extend": { "version": "3.0.2", - "resolved": false, - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + "bundled": true }, "extsprintf": { "version": "1.3.0", - "resolved": false, - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "bundled": true }, "fast-deep-equal": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + "bundled": true }, "fast-json-stable-stringify": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + "bundled": true }, "figgy-pudding": { "version": "3.5.1", - "resolved": false, - "integrity": "sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==" + "bundled": true }, "find-npm-prefix": { "version": "1.0.2", - "resolved": false, - "integrity": "sha512-KEftzJ+H90x6pcKtdXZEPsQse8/y/UnvzRKrOSQFprnrGaFuJ62fVkP34Iu2IYuMvyauCyoLTNkJZgrrGA2wkA==" + "bundled": true }, "find-up": { "version": "2.1.0", - "resolved": false, - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "bundled": true, "requires": { "locate-path": "^2.0.0" } }, "flush-write-stream": { "version": "1.0.3", - "resolved": false, - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", + "bundled": true, "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.4" @@ -3528,8 +3733,7 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3542,8 +3746,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "requires": { "safe-buffer": "~5.1.0" } @@ -3552,13 +3755,11 @@ }, "forever-agent": { "version": "0.6.1", - "resolved": false, - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + "bundled": true }, "form-data": { "version": "2.3.2", - "resolved": false, - "integrity": "sha1-SXBJi+YEwgwAXU9cI67NIda0kJk=", + "bundled": true, "requires": { "asynckit": "^0.4.0", "combined-stream": "1.0.6", @@ -3567,8 +3768,7 @@ }, "from2": { "version": "2.3.0", - "resolved": false, - "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "bundled": true, "requires": { "inherits": "^2.0.1", "readable-stream": "^2.0.0" @@ -3576,8 +3776,7 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3590,8 +3789,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "requires": { "safe-buffer": "~5.1.0" } @@ -3600,16 +3798,14 @@ }, "fs-minipass": { "version": "1.2.7", - "resolved": false, - "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "bundled": true, "requires": { "minipass": "^2.6.0" }, "dependencies": { "minipass": { "version": "2.9.0", - "resolved": false, - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "bundled": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -3619,8 +3815,7 @@ }, "fs-vacuum": { "version": "1.2.10", - "resolved": false, - "integrity": "sha1-t2Kb7AekAxolSP35n17PHMizHjY=", + "bundled": true, "requires": { "graceful-fs": "^4.1.2", "path-is-inside": "^1.0.1", @@ -3629,8 +3824,7 @@ }, "fs-write-stream-atomic": { "version": "1.0.10", - "resolved": false, - "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "bundled": true, "requires": { "graceful-fs": "^4.1.2", "iferr": "^0.1.5", @@ -3640,13 +3834,11 @@ "dependencies": { "iferr": { "version": "0.1.5", - "resolved": false, - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + "bundled": true }, "readable-stream": { "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -3659,8 +3851,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "requires": { "safe-buffer": "~5.1.0" } @@ -3669,18 +3860,15 @@ }, "fs.realpath": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + "bundled": true }, "function-bind": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "bundled": true }, "gauge": { "version": "2.7.4", - "resolved": false, - "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "bundled": true, "requires": { "aproba": "^1.0.3", "console-control-strings": "^1.0.0", @@ -3694,13 +3882,11 @@ "dependencies": { "aproba": { "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "bundled": true }, "string-width": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -3711,16 +3897,15 @@ }, "genfun": { "version": "5.0.0", - "resolved": false, - "integrity": "sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA==" + "bundled": true }, "gentle-fs": { - "version": "2.2.1", - "resolved": false, - "integrity": "sha512-e7dRgUM5fsS+7wm2oggZpgcRx6sEvJHXujPH5RzgQ1ziQY4+HuVBYsnUzJwJ+C7mjOJN27DjiFy1TaL+TNltow==", + "version": "2.3.0", + "bundled": true, "requires": { "aproba": "^1.1.2", "chownr": "^1.1.2", + "cmd-shim": "^3.0.3", "fs-vacuum": "^1.2.10", "graceful-fs": "^4.1.11", "iferr": "^0.1.5", @@ -3733,41 +3918,35 @@ "dependencies": { "aproba": { "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "bundled": true }, "iferr": { "version": "0.1.5", - "resolved": false, - "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=" + "bundled": true } } }, "get-caller-file": { - "version": "1.0.2", - "resolved": false, - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" + "version": "1.0.3", + "bundled": true }, "get-stream": { "version": "4.1.0", - "resolved": false, - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "bundled": true, "requires": { "pump": "^3.0.0" } }, "getpass": { "version": "0.1.7", - "resolved": false, - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "bundled": true, "requires": { "assert-plus": "^1.0.0" } }, "glob": { - "version": "7.1.4", - "resolved": false, - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "version": "7.1.6", + "bundled": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -3779,16 +3958,14 @@ }, "global-dirs": { "version": "0.1.1", - "resolved": false, - "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "bundled": true, "requires": { "ini": "^1.3.4" } }, "got": { "version": "6.7.1", - "resolved": false, - "integrity": "sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA=", + "bundled": true, "requires": { "create-error-class": "^3.0.0", "duplexer3": "^0.1.4", @@ -3805,25 +3982,21 @@ "dependencies": { "get-stream": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + "bundled": true } } }, "graceful-fs": { "version": "4.2.3", - "resolved": false, - "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" + "bundled": true }, "har-schema": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + "bundled": true }, "har-validator": { "version": "5.1.0", - "resolved": false, - "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "bundled": true, "requires": { "ajv": "^5.3.0", "har-schema": "^2.0.0" @@ -3831,41 +4004,34 @@ }, "has": { "version": "1.0.3", - "resolved": false, - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "bundled": true, "requires": { "function-bind": "^1.1.1" } }, "has-flag": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + "bundled": true }, "has-symbols": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + "bundled": true }, "has-unicode": { "version": "2.0.1", - "resolved": false, - "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + "bundled": true }, "hosted-git-info": { - "version": "2.8.5", - "resolved": false, - "integrity": "sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg==" + "version": "2.8.8", + "bundled": true }, "http-cache-semantics": { "version": "3.8.1", - "resolved": false, - "integrity": "sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w==" + "bundled": true }, "http-proxy-agent": { "version": "2.1.0", - "resolved": false, - "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==", + "bundled": true, "requires": { "agent-base": "4", "debug": "3.1.0" @@ -3873,8 +4039,7 @@ }, "http-signature": { "version": "1.2.0", - "resolved": false, - "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "bundled": true, "requires": { "assert-plus": "^1.0.0", "jsprim": "^1.2.2", @@ -3883,8 +4048,7 @@ }, "https-proxy-agent": { "version": "2.2.4", - "resolved": false, - "integrity": "sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg==", + "bundled": true, "requires": { "agent-base": "^4.3.0", "debug": "^3.1.0" @@ -3892,52 +4056,44 @@ }, "humanize-ms": { "version": "1.2.1", - "resolved": false, - "integrity": "sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0=", + "bundled": true, "requires": { "ms": "^2.0.0" } }, "iconv-lite": { "version": "0.4.23", - "resolved": false, - "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "bundled": true, "requires": { "safer-buffer": ">= 2.1.2 < 3" } }, "iferr": { "version": "1.0.2", - "resolved": false, - "integrity": "sha512-9AfeLfji44r5TKInjhz3W9DyZI1zR1JAf2hVBMGhddAKPqBsupb89jGfbCTHIGZd6fGZl9WlHdn4AObygyMKwg==" + "bundled": true }, "ignore-walk": { "version": "3.0.3", - "resolved": false, - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "bundled": true, "requires": { "minimatch": "^3.0.4" } }, "import-lazy": { "version": "2.1.0", - "resolved": false, - "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + "bundled": true }, "imurmurhash": { "version": "0.1.4", - "resolved": false, - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + "bundled": true }, "infer-owner": { "version": "1.0.4", - "resolved": false, - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" + "bundled": true }, "inflight": { "version": "1.0.6", - "resolved": false, - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "bundled": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -3945,18 +4101,15 @@ }, "inherits": { "version": "2.0.4", - "resolved": false, - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "bundled": true }, "ini": { "version": "1.3.5", - "resolved": false, - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + "bundled": true }, "init-package-json": { "version": "1.10.3", - "resolved": false, - "integrity": "sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw==", + "bundled": true, "requires": { "glob": "^7.1.1", "npm-package-arg": "^4.0.0 || ^5.0.0 || ^6.0.0", @@ -3969,65 +4122,55 @@ } }, "invert-kv": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + "version": "2.0.0", + "bundled": true }, "ip": { "version": "1.1.5", - "resolved": false, - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + "bundled": true }, "ip-regex": { "version": "2.1.0", - "resolved": false, - "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=" + "bundled": true }, "is-callable": { "version": "1.1.4", - "resolved": false, - "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" + "bundled": true }, "is-ci": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", + "version": "1.2.1", + "bundled": true, "requires": { - "ci-info": "^1.0.0" + "ci-info": "^1.5.0" }, "dependencies": { "ci-info": { "version": "1.6.0", - "resolved": false, - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==" + "bundled": true } } }, "is-cidr": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-8Xnnbjsb0x462VoYiGlhEi+drY8SFwrHiSYuzc/CEwco55vkehTaxAyIjEdpi3EMvLPPJAJi9FlzP+h+03gp0Q==", + "bundled": true, "requires": { "cidr-regex": "^2.0.10" } }, "is-date-object": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" + "bundled": true }, "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "bundled": true, "requires": { "number-is-nan": "^1.0.0" } }, "is-installed-globally": { "version": "0.1.0", - "resolved": false, - "integrity": "sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA=", + "bundled": true, "requires": { "global-dirs": "^0.1.0", "is-path-inside": "^1.0.0" @@ -4035,108 +4178,89 @@ }, "is-npm": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-8vtjpl5JBbQGyGBydloaTceTufQ=" + "bundled": true }, "is-obj": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + "bundled": true }, "is-path-inside": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "bundled": true, "requires": { "path-is-inside": "^1.0.1" } }, "is-redirect": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=" + "bundled": true }, "is-regex": { "version": "1.0.4", - "resolved": false, - "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "bundled": true, "requires": { "has": "^1.0.1" } }, "is-retry-allowed": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=" + "version": "1.2.0", + "bundled": true }, "is-stream": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "bundled": true }, "is-symbol": { "version": "1.0.2", - "resolved": false, - "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==", + "bundled": true, "requires": { "has-symbols": "^1.0.0" } }, "is-typedarray": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + "bundled": true }, "isarray": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "bundled": true }, "isexe": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + "bundled": true }, "isstream": { "version": "0.1.2", - "resolved": false, - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + "bundled": true }, "jsbn": { "version": "0.1.1", - "resolved": false, - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "bundled": true, "optional": true }, "json-parse-better-errors": { "version": "1.0.2", - "resolved": false, - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + "bundled": true }, "json-schema": { "version": "0.2.3", - "resolved": false, - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + "bundled": true }, "json-schema-traverse": { "version": "0.3.1", - "resolved": false, - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + "bundled": true }, "json-stringify-safe": { "version": "5.0.1", - "resolved": false, - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + "bundled": true }, "jsonparse": { "version": "1.3.1", - "resolved": false, - "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=" + "bundled": true }, "jsprim": { "version": "1.4.1", - "resolved": false, - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "bundled": true, "requires": { "assert-plus": "1.0.0", "extsprintf": "1.3.0", @@ -4146,29 +4270,25 @@ }, "latest-version": { "version": "3.1.0", - "resolved": false, - "integrity": "sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU=", + "bundled": true, "requires": { "package-json": "^4.0.0" } }, "lazy-property": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-hN3Es3Bnm6i9TNz6TAa0PVcREUc=" + "bundled": true }, "lcid": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "version": "2.0.0", + "bundled": true, "requires": { - "invert-kv": "^1.0.0" + "invert-kv": "^2.0.0" } }, "libcipm": { "version": "4.0.7", - "resolved": false, - "integrity": "sha512-fTq33otU3PNXxxCTCYCYe7V96o59v/o7bvtspmbORXpgFk+wcWrGf5x6tBgui5gCed/45/wtPomBsZBYm5KbIw==", + "bundled": true, "requires": { "bin-links": "^1.1.2", "bluebird": "^3.5.1", @@ -4189,8 +4309,7 @@ }, "libnpm": { "version": "3.0.1", - "resolved": false, - "integrity": "sha512-d7jU5ZcMiTfBqTUJVZ3xid44fE5ERBm9vBnmhp2ECD2Ls+FNXWxHSkO7gtvrnbLO78gwPdNPz1HpsF3W4rjkBQ==", + "bundled": true, "requires": { "bin-links": "^1.1.2", "bluebird": "^3.5.3", @@ -4216,8 +4335,7 @@ }, "libnpmaccess": { "version": "3.0.2", - "resolved": false, - "integrity": "sha512-01512AK7MqByrI2mfC7h5j8N9V4I7MHJuk9buo8Gv+5QgThpOgpjB7sQBDDkeZqRteFb1QM/6YNdHfG7cDvfAQ==", + "bundled": true, "requires": { "aproba": "^2.0.0", "get-stream": "^4.0.0", @@ -4227,8 +4345,7 @@ }, "libnpmconfig": { "version": "1.2.1", - "resolved": false, - "integrity": "sha512-9esX8rTQAHqarx6qeZqmGQKBNZR5OIbl/Ayr0qQDy3oXja2iFVQQI81R6GZ2a02bSNZ9p3YOGX1O6HHCb1X7kA==", + "bundled": true, "requires": { "figgy-pudding": "^3.5.1", "find-up": "^3.0.0", @@ -4237,16 +4354,14 @@ "dependencies": { "find-up": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "bundled": true, "requires": { "locate-path": "^3.0.0" } }, "locate-path": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "bundled": true, "requires": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" @@ -4254,31 +4369,27 @@ }, "p-limit": { "version": "2.2.0", - "resolved": false, - "integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==", + "bundled": true, "requires": { "p-try": "^2.0.0" } }, "p-locate": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "bundled": true, "requires": { "p-limit": "^2.0.0" } }, "p-try": { "version": "2.2.0", - "resolved": false, - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "bundled": true } } }, "libnpmhook": { "version": "5.0.3", - "resolved": false, - "integrity": "sha512-UdNLMuefVZra/wbnBXECZPefHMGsVDTq5zaM/LgKNE9Keyl5YXQTnGAzEo+nFOpdRqTWI9LYi4ApqF9uVCCtuA==", + "bundled": true, "requires": { "aproba": "^2.0.0", "figgy-pudding": "^3.4.1", @@ -4288,8 +4399,7 @@ }, "libnpmorg": { "version": "1.0.1", - "resolved": false, - "integrity": "sha512-0sRUXLh+PLBgZmARvthhYXQAWn0fOsa6T5l3JSe2n9vKG/lCVK4nuG7pDsa7uMq+uTt2epdPK+a2g6btcY11Ww==", + "bundled": true, "requires": { "aproba": "^2.0.0", "figgy-pudding": "^3.4.1", @@ -4299,8 +4409,7 @@ }, "libnpmpublish": { "version": "1.1.2", - "resolved": false, - "integrity": "sha512-2yIwaXrhTTcF7bkJKIKmaCV9wZOALf/gsTDxVSu/Gu/6wiG3fA8ce8YKstiWKTxSFNC0R7isPUb6tXTVFZHt2g==", + "bundled": true, "requires": { "aproba": "^2.0.0", "figgy-pudding": "^3.5.1", @@ -4315,8 +4424,7 @@ }, "libnpmsearch": { "version": "2.0.2", - "resolved": false, - "integrity": "sha512-VTBbV55Q6fRzTdzziYCr64+f8AopQ1YZ+BdPOv16UegIEaE8C0Kch01wo4s3kRTFV64P121WZJwgmBwrq68zYg==", + "bundled": true, "requires": { "figgy-pudding": "^3.5.1", "get-stream": "^4.0.0", @@ -4325,8 +4433,7 @@ }, "libnpmteam": { "version": "1.0.2", - "resolved": false, - "integrity": "sha512-p420vM28Us04NAcg1rzgGW63LMM6rwe+6rtZpfDxCcXxM0zUTLl7nPFEnRF3JfFBF5skF/yuZDUthTsHgde8QA==", + "bundled": true, "requires": { "aproba": "^2.0.0", "figgy-pudding": "^3.4.1", @@ -4335,9 +4442,8 @@ } }, "libnpx": { - "version": "10.2.0", - "resolved": false, - "integrity": "sha512-X28coei8/XRCt15cYStbLBph+KGhFra4VQhRBPuH/HHMkC5dxM8v24RVgUsvODKCrUZ0eTgiTqJp6zbl0sskQQ==", + "version": "10.2.2", + "bundled": true, "requires": { "dotenv": "^5.0.1", "npm-package-arg": "^6.0.0", @@ -4351,8 +4457,7 @@ }, "locate-path": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "bundled": true, "requires": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -4360,8 +4465,7 @@ }, "lock-verify": { "version": "2.1.0", - "resolved": false, - "integrity": "sha512-vcLpxnGvrqisKvLQ2C2v0/u7LVly17ak2YSgoK4PrdsYBXQIax19vhKiLfvKNFx7FRrpTnitrpzF/uuCMuorIg==", + "bundled": true, "requires": { "npm-package-arg": "^6.1.0", "semver": "^5.4.1" @@ -4369,21 +4473,18 @@ }, "lockfile": { "version": "1.0.4", - "resolved": false, - "integrity": "sha512-cvbTwETRfsFh4nHsL1eGWapU1XFi5Ot9E85sWAwia7Y7EgB7vfqcZhTKZ+l7hCGxSPoushMv5GKhT5PdLv03WA==", + "bundled": true, "requires": { "signal-exit": "^3.0.2" } }, "lodash._baseindexof": { "version": "3.1.0", - "resolved": false, - "integrity": "sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw=" + "bundled": true }, "lodash._baseuniq": { "version": "4.6.0", - "resolved": false, - "integrity": "sha1-DrtE5FaBSveQXGIS+iybLVG4Qeg=", + "bundled": true, "requires": { "lodash._createset": "~4.0.0", "lodash._root": "~3.0.0" @@ -4391,87 +4492,72 @@ }, "lodash._bindcallback": { "version": "3.0.1", - "resolved": false, - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=" + "bundled": true }, "lodash._cacheindexof": { "version": "3.0.2", - "resolved": false, - "integrity": "sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI=" + "bundled": true }, "lodash._createcache": { "version": "3.1.2", - "resolved": false, - "integrity": "sha1-VtagZAF2JeeevKa4AY4XRAvc8JM=", + "bundled": true, "requires": { "lodash._getnative": "^3.0.0" } }, "lodash._createset": { "version": "4.0.3", - "resolved": false, - "integrity": "sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY=" + "bundled": true }, "lodash._getnative": { "version": "3.9.1", - "resolved": false, - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=" + "bundled": true }, "lodash._root": { "version": "3.0.1", - "resolved": false, - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=" + "bundled": true }, "lodash.clonedeep": { "version": "4.5.0", - "resolved": false, - "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=" + "bundled": true }, "lodash.restparam": { "version": "3.6.1", - "resolved": false, - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=" + "bundled": true }, "lodash.union": { "version": "4.6.0", - "resolved": false, - "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + "bundled": true }, "lodash.uniq": { "version": "4.5.0", - "resolved": false, - "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=" + "bundled": true }, "lodash.without": { "version": "4.4.0", - "resolved": false, - "integrity": "sha1-PNRXSgC2e643OpS3SHcmQFB7eqw=" + "bundled": true }, "lowercase-keys": { "version": "1.0.1", - "resolved": false, - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + "bundled": true }, "lru-cache": { "version": "5.1.1", - "resolved": false, - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "bundled": true, "requires": { "yallist": "^3.0.2" } }, "make-dir": { "version": "1.3.0", - "resolved": false, - "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "bundled": true, "requires": { "pify": "^3.0.0" } }, "make-fetch-happen": { "version": "5.0.2", - "resolved": false, - "integrity": "sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag==", + "bundled": true, "requires": { "agentkeepalive": "^3.4.1", "cacache": "^12.0.0", @@ -4486,62 +4572,60 @@ "ssri": "^6.0.0" } }, + "map-age-cleaner": { + "version": "0.1.3", + "bundled": true, + "requires": { + "p-defer": "^1.0.0" + } + }, "meant": { "version": "1.0.1", - "resolved": false, - "integrity": "sha512-UakVLFjKkbbUwNWJ2frVLnnAtbb7D7DsloxRd3s/gDpI8rdv8W5Hp3NaDb+POBI1fQdeussER6NB8vpcRURvlg==" + "bundled": true }, "mem": { - "version": "1.1.0", - "resolved": false, - "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "version": "4.3.0", + "bundled": true, "requires": { - "mimic-fn": "^1.0.0" + "map-age-cleaner": "^0.1.1", + "mimic-fn": "^2.0.0", + "p-is-promise": "^2.0.0" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "bundled": true + } } }, "mime-db": { "version": "1.35.0", - "resolved": false, - "integrity": "sha512-JWT/IcCTsB0Io3AhWUMjRqucrHSPsSf2xKLaRldJVULioggvkJvggZ3VXNNSRkCddE6D+BUI4HEIZIA2OjwIvg==" + "bundled": true }, "mime-types": { "version": "2.1.19", - "resolved": false, - "integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==", + "bundled": true, "requires": { "mime-db": "~1.35.0" } }, - "mimic-fn": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" - }, "minimatch": { "version": "3.0.4", - "resolved": false, - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "bundled": true, "requires": { "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "0.0.8", - "resolved": false, - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" - }, "minizlib": { "version": "1.3.3", - "resolved": false, - "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "bundled": true, "requires": { "minipass": "^2.9.0" }, "dependencies": { "minipass": { "version": "2.9.0", - "resolved": false, - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "bundled": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4551,8 +4635,7 @@ }, "mississippi": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "bundled": true, "requires": { "concat-stream": "^1.5.0", "duplexify": "^3.4.2", @@ -4567,17 +4650,21 @@ } }, "mkdirp": { - "version": "0.5.1", - "resolved": false, - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "version": "0.5.4", + "bundled": true, "requires": { - "minimist": "0.0.8" + "minimist": "^1.2.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.5", + "bundled": true + } } }, "move-concurrently": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "bundled": true, "requires": { "aproba": "^1.1.1", "copy-concurrently": "^1.0.0", @@ -4589,25 +4676,25 @@ "dependencies": { "aproba": { "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "bundled": true } } }, "ms": { "version": "2.1.1", - "resolved": false, - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "bundled": true }, "mute-stream": { "version": "0.0.7", - "resolved": false, - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=" + "bundled": true + }, + "nice-try": { + "version": "1.0.5", + "bundled": true }, "node-fetch-npm": { "version": "2.0.2", - "resolved": false, - "integrity": "sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw==", + "bundled": true, "requires": { "encoding": "^0.1.11", "json-parse-better-errors": "^1.0.0", @@ -4615,42 +4702,25 @@ } }, "node-gyp": { - "version": "5.0.5", - "resolved": false, - "integrity": "sha512-WABl9s4/mqQdZneZHVWVG4TVr6QQJZUC6PAx47ITSk9lreZ1n+7Z9mMAIbA3vnO4J9W20P7LhCxtzfWsAD/KDw==", + "version": "5.1.0", + "bundled": true, "requires": { - "env-paths": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "mkdirp": "^0.5.1", + "nopt": "^4.0.1", + "npmlog": "^4.1.2", + "request": "^2.88.0", + "rimraf": "^2.6.3", + "semver": "^5.7.1", "tar": "^4.4.12", - "which": "1" - }, - "dependencies": { - "nopt": { - "version": "3.0.6", - "resolved": false, - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "requires": { - "abbrev": "1" - } - }, - "semver": { - "version": "5.3.0", - "resolved": false, - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" - } + "which": "^1.3.1" } }, "nopt": { "version": "4.0.1", - "resolved": false, - "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "bundled": true, "requires": { "abbrev": "1", "osenv": "^0.1.4" @@ -4658,8 +4728,7 @@ }, "normalize-package-data": { "version": "2.5.0", - "resolved": false, - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "bundled": true, "requires": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", @@ -4669,8 +4738,7 @@ "dependencies": { "resolve": { "version": "1.10.0", - "resolved": false, - "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==", + "bundled": true, "requires": { "path-parse": "^1.0.6" } @@ -4679,35 +4747,33 @@ }, "npm-audit-report": { "version": "1.3.2", - "resolved": false, - "integrity": "sha512-abeqS5ONyXNaZJPGAf6TOUMNdSe1Y6cpc9MLBRn+CuUoYbfdca6AxOyXVlfIv9OgKX+cacblbG5w7A6ccwoTPw==", + "bundled": true, "requires": { "cli-table3": "^0.5.0", "console-control-strings": "^1.1.0" } }, "npm-bundled": { - "version": "1.0.6", - "resolved": false, - "integrity": "sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g==" + "version": "1.1.1", + "bundled": true, + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } }, "npm-cache-filename": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-3tMGxbC/yHCp6fr4I7xfKD4FrhE=" + "bundled": true }, "npm-install-checks": { "version": "3.0.2", - "resolved": false, - "integrity": "sha512-E4kzkyZDIWoin6uT5howP8VDvkM+E8IQDcHAycaAxMbwkqhIg5eEYALnXOl3Hq9MrkdQB/2/g1xwBINXdKSRkg==", + "bundled": true, "requires": { "semver": "^2.3.0 || 3.x || 4 || 5" } }, "npm-lifecycle": { "version": "3.1.4", - "resolved": false, - "integrity": "sha512-tgs1PaucZwkxECGKhC/stbEgFyc3TGh2TJcg2CDr6jbvQRdteHNhmMeljRzpe4wgFAXQADoy1cSqqi7mtiAa5A==", + "bundled": true, "requires": { "byline": "^5.0.0", "graceful-fs": "^4.1.15", @@ -4721,13 +4787,15 @@ }, "npm-logical-tree": { "version": "1.2.1", - "resolved": false, - "integrity": "sha512-AJI/qxDB2PWI4LG1CYN579AY1vCiNyWfkiquCsJWqntRu/WwimVrC8yXeILBFHDwxfOejxewlmnvW9XXjMlYIg==" + "bundled": true + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "bundled": true }, "npm-package-arg": { "version": "6.1.1", - "resolved": false, - "integrity": "sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg==", + "bundled": true, "requires": { "hosted-git-info": "^2.7.1", "osenv": "^0.1.5", @@ -4736,18 +4804,17 @@ } }, "npm-packlist": { - "version": "1.4.6", - "resolved": false, - "integrity": "sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg==", + "version": "1.4.8", + "bundled": true, "requires": { "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" } }, "npm-pick-manifest": { "version": "3.0.2", - "resolved": false, - "integrity": "sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw==", + "bundled": true, "requires": { "figgy-pudding": "^3.5.1", "npm-package-arg": "^6.0.0", @@ -4755,9 +4822,8 @@ } }, "npm-profile": { - "version": "4.0.2", - "resolved": false, - "integrity": "sha512-VRsC04pvRH+9cF+PoVh2nTmJjiG21yu59IHpsBpkxk+jaGAV8lxx96G4SDc0jOHAkfWLXbc6kIph3dGAuRnotQ==", + "version": "4.0.4", + "bundled": true, "requires": { "aproba": "^1.1.2 || 2", "figgy-pudding": "^3.4.1", @@ -4765,9 +4831,8 @@ } }, "npm-registry-fetch": { - "version": "4.0.2", - "resolved": false, - "integrity": "sha512-Z0IFtPEozNdeZRPh3aHHxdG+ZRpzcbQaJLthsm3VhNf6DScicTFRHZzK82u8RsJUsUHkX+QH/zcB/5pmd20H4A==", + "version": "4.0.3", + "bundled": true, "requires": { "JSONStream": "^1.3.4", "bluebird": "^3.5.1", @@ -4780,28 +4845,24 @@ "dependencies": { "safe-buffer": { "version": "5.2.0", - "resolved": false, - "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + "bundled": true } } }, "npm-run-path": { "version": "2.0.2", - "resolved": false, - "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "bundled": true, "requires": { "path-key": "^2.0.0" } }, "npm-user-validate": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-jOyg9c6gTU6TUZ73LQVXp1Ei6VE=" + "bundled": true }, "npmlog": { "version": "4.1.2", - "resolved": false, - "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "bundled": true, "requires": { "are-we-there-yet": "~1.1.2", "console-control-strings": "~1.1.0", @@ -4811,28 +4872,23 @@ }, "number-is-nan": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + "bundled": true }, "oauth-sign": { "version": "0.9.0", - "resolved": false, - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + "bundled": true }, "object-assign": { "version": "4.1.1", - "resolved": false, - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "bundled": true }, "object-keys": { "version": "1.0.12", - "resolved": false, - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==" + "bundled": true }, "object.getownpropertydescriptors": { "version": "2.0.3", - "resolved": false, - "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "bundled": true, "requires": { "define-properties": "^1.1.2", "es-abstract": "^1.5.1" @@ -4840,76 +4896,99 @@ }, "once": { "version": "1.4.0", - "resolved": false, - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "bundled": true, "requires": { "wrappy": "1" } }, "opener": { "version": "1.5.1", - "resolved": false, - "integrity": "sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA==" + "bundled": true }, "os-homedir": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + "bundled": true }, "os-locale": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "version": "3.1.0", + "bundled": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" + "execa": "^1.0.0", + "lcid": "^2.0.0", + "mem": "^4.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "bundled": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "bundled": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + } } }, "os-tmpdir": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + "bundled": true }, "osenv": { "version": "0.1.5", - "resolved": false, - "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "bundled": true, "requires": { "os-homedir": "^1.0.0", "os-tmpdir": "^1.0.0" } }, + "p-defer": { + "version": "1.0.0", + "bundled": true + }, "p-finally": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + "bundled": true + }, + "p-is-promise": { + "version": "2.1.0", + "bundled": true }, "p-limit": { "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "bundled": true, "requires": { "p-try": "^1.0.0" } }, "p-locate": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "bundled": true, "requires": { "p-limit": "^1.1.0" } }, "p-try": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + "bundled": true }, "package-json": { "version": "4.0.1", - "resolved": false, - "integrity": "sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0=", + "bundled": true, "requires": { "got": "^6.7.1", "registry-auth-token": "^3.0.1", @@ -4918,9 +4997,8 @@ } }, "pacote": { - "version": "9.5.9", - "resolved": false, - "integrity": "sha512-S1nYW9ly+3btn3VmwRAk2LG3TEh8mkrFdY+psbnHSk8oPODbZ28uG0Z0d3yI0EpqcpLR6BukoVRf3H4IbGCkPQ==", + "version": "9.5.12", + "bundled": true, "requires": { "bluebird": "^3.5.3", "cacache": "^12.0.2", @@ -4936,6 +5014,7 @@ "mississippi": "^3.0.0", "mkdirp": "^0.5.1", "normalize-package-data": "^2.4.0", + "npm-normalize-package-bin": "^1.0.0", "npm-package-arg": "^6.1.0", "npm-packlist": "^1.1.12", "npm-pick-manifest": "^3.0.0", @@ -4955,8 +5034,7 @@ "dependencies": { "minipass": { "version": "2.9.0", - "resolved": false, - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "bundled": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4966,8 +5044,7 @@ }, "parallel-transform": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", + "bundled": true, "requires": { "cyclist": "~0.2.2", "inherits": "^2.0.3", @@ -4976,8 +5053,7 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -4990,8 +5066,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "requires": { "safe-buffer": "~5.1.0" } @@ -5000,58 +5075,47 @@ }, "path-exists": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "bundled": true }, "path-is-absolute": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + "bundled": true }, "path-is-inside": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=" + "bundled": true }, "path-key": { "version": "2.0.1", - "resolved": false, - "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + "bundled": true }, "path-parse": { "version": "1.0.6", - "resolved": false, - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + "bundled": true }, "performance-now": { "version": "2.1.0", - "resolved": false, - "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + "bundled": true }, "pify": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" + "bundled": true }, "prepend-http": { "version": "1.0.4", - "resolved": false, - "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw=" + "bundled": true }, "process-nextick-args": { "version": "2.0.0", - "resolved": false, - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + "bundled": true }, "promise-inflight": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=" + "bundled": true }, "promise-retry": { "version": "1.1.1", - "resolved": false, - "integrity": "sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0=", + "bundled": true, "requires": { "err-code": "^1.0.0", "retry": "^0.10.0" @@ -5059,51 +5123,43 @@ "dependencies": { "retry": { "version": "0.10.1", - "resolved": false, - "integrity": "sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q=" + "bundled": true } } }, "promzard": { "version": "0.3.0", - "resolved": false, - "integrity": "sha1-JqXW7ox97kyxIggwWs+5O6OCqe4=", + "bundled": true, "requires": { "read": "1" } }, "proto-list": { "version": "1.2.4", - "resolved": false, - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + "bundled": true }, "protoduck": { "version": "5.0.1", - "resolved": false, - "integrity": "sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg==", + "bundled": true, "requires": { "genfun": "^5.0.0" } }, "prr": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=" + "bundled": true }, "pseudomap": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + "bundled": true }, "psl": { "version": "1.1.29", - "resolved": false, - "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + "bundled": true }, "pump": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "bundled": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -5111,8 +5167,7 @@ }, "pumpify": { "version": "1.5.1", - "resolved": false, - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "bundled": true, "requires": { "duplexify": "^3.6.0", "inherits": "^2.0.3", @@ -5121,8 +5176,7 @@ "dependencies": { "pump": { "version": "2.0.1", - "resolved": false, - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "bundled": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -5132,23 +5186,19 @@ }, "punycode": { "version": "1.4.1", - "resolved": false, - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + "bundled": true }, "qrcode-terminal": { "version": "0.12.0", - "resolved": false, - "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==" + "bundled": true }, "qs": { "version": "6.5.2", - "resolved": false, - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "bundled": true }, "query-string": { "version": "6.8.2", - "resolved": false, - "integrity": "sha512-J3Qi8XZJXh93t2FiKyd/7Ec6GNifsjKXUsVFkSBj/kjLsDylWhnCz4NT1bkPcKotttPW+QbKGqqPH8OoI2pdqw==", + "bundled": true, "requires": { "decode-uri-component": "^0.2.0", "split-on-first": "^1.0.0", @@ -5157,47 +5207,41 @@ }, "qw": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-77/cdA+a0FQwRCassYNBLMi5ltQ=" + "bundled": true }, "rc": { - "version": "1.2.7", - "resolved": false, - "integrity": "sha512-LdLD8xD4zzLsAT5xyushXDNscEjB7+2ulnl8+r1pnESlYtlJtVSoCMBGr30eDRJ3+2Gq89jK9P9e4tCEH1+ywA==", + "version": "1.2.8", + "bundled": true, "requires": { - "deep-extend": "^0.5.1", + "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "dependencies": { "minimist": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + "version": "1.2.5", + "bundled": true } } }, "read": { "version": "1.0.7", - "resolved": false, - "integrity": "sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ=", + "bundled": true, "requires": { "mute-stream": "~0.0.4" } }, "read-cmd-shim": { "version": "1.0.5", - "resolved": false, - "integrity": "sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA==", + "bundled": true, "requires": { "graceful-fs": "^4.1.2" } }, "read-installed": { "version": "4.0.3", - "resolved": false, - "integrity": "sha1-/5uLZ/GH0eTCm5/rMfayI6zRkGc=", + "bundled": true, "requires": { "debuglog": "^1.0.1", "graceful-fs": "^4.1.2", @@ -5209,21 +5253,19 @@ } }, "read-package-json": { - "version": "2.1.0", - "resolved": false, - "integrity": "sha512-KLhu8M1ZZNkMcrq1+0UJbR8Dii8KZUqB0Sha4mOx/bknfKI/fyrQVrG/YIt2UOtG667sD8+ee4EXMM91W9dC+A==", + "version": "2.1.1", + "bundled": true, "requires": { "glob": "^7.1.1", "graceful-fs": "^4.1.2", "json-parse-better-errors": "^1.0.1", "normalize-package-data": "^2.0.0", - "slash": "^1.0.0" + "npm-normalize-package-bin": "^1.0.0" } }, "read-package-tree": { "version": "5.3.1", - "resolved": false, - "integrity": "sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw==", + "bundled": true, "requires": { "read-package-json": "^2.0.0", "readdir-scoped-modules": "^1.0.0", @@ -5231,9 +5273,8 @@ } }, "readable-stream": { - "version": "3.4.0", - "resolved": false, - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "version": "3.6.0", + "bundled": true, "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -5242,8 +5283,7 @@ }, "readdir-scoped-modules": { "version": "1.1.0", - "resolved": false, - "integrity": "sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==", + "bundled": true, "requires": { "debuglog": "^1.0.1", "dezalgo": "^1.0.0", @@ -5252,9 +5292,8 @@ } }, "registry-auth-token": { - "version": "3.3.2", - "resolved": false, - "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "version": "3.4.0", + "bundled": true, "requires": { "rc": "^1.1.6", "safe-buffer": "^5.0.1" @@ -5262,16 +5301,14 @@ }, "registry-url": { "version": "3.1.0", - "resolved": false, - "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "bundled": true, "requires": { "rc": "^1.0.1" } }, "request": { "version": "2.88.0", - "resolved": false, - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "bundled": true, "requires": { "aws-sign2": "~0.7.0", "aws4": "^1.8.0", @@ -5297,120 +5334,96 @@ }, "require-directory": { "version": "2.1.1", - "resolved": false, - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "bundled": true }, "require-main-filename": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + "bundled": true }, "resolve-from": { "version": "4.0.0", - "resolved": false, - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + "bundled": true }, "retry": { "version": "0.12.0", - "resolved": false, - "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=" + "bundled": true }, "rimraf": { - "version": "2.6.3", - "resolved": false, - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "2.7.1", + "bundled": true, "requires": { "glob": "^7.1.3" } }, "run-queue": { "version": "1.0.3", - "resolved": false, - "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "bundled": true, "requires": { "aproba": "^1.1.1" }, "dependencies": { "aproba": { "version": "1.2.0", - "resolved": false, - "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + "bundled": true } } }, "safe-buffer": { "version": "5.1.2", - "resolved": false, - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "bundled": true }, "safer-buffer": { "version": "2.1.2", - "resolved": false, - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "bundled": true }, "semver": { "version": "5.7.1", - "resolved": false, - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "bundled": true }, "semver-diff": { "version": "2.1.0", - "resolved": false, - "integrity": "sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY=", + "bundled": true, "requires": { "semver": "^5.0.3" } }, "set-blocking": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "bundled": true }, "sha": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-DOYnM37cNsLNSGIG/zZWch5CKIRNoLdYUQTQlcgkRkoYIUwDYjqDyye16YcDZg/OPdcbUgTKMjc4SY6TB7ZAPw==", + "bundled": true, "requires": { "graceful-fs": "^4.1.2" } }, "shebang-command": { "version": "1.2.0", - "resolved": false, - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "bundled": true, "requires": { "shebang-regex": "^1.0.0" } }, "shebang-regex": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + "bundled": true }, "signal-exit": { "version": "3.0.2", - "resolved": false, - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" - }, - "slash": { - "version": "1.0.0", - "resolved": false, - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=" + "bundled": true }, "slide": { "version": "1.1.6", - "resolved": false, - "integrity": "sha1-VusCfWW00tzmyy4tMsTUr8nh1wc=" + "bundled": true }, "smart-buffer": { "version": "4.1.0", - "resolved": false, - "integrity": "sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw==" + "bundled": true }, "socks": { "version": "2.3.3", - "resolved": false, - "integrity": "sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA==", + "bundled": true, "requires": { "ip": "1.1.5", "smart-buffer": "^4.1.0" @@ -5418,8 +5431,7 @@ }, "socks-proxy-agent": { "version": "4.0.2", - "resolved": false, - "integrity": "sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg==", + "bundled": true, "requires": { "agent-base": "~4.2.1", "socks": "~2.3.2" @@ -5427,8 +5439,7 @@ "dependencies": { "agent-base": { "version": "4.2.1", - "resolved": false, - "integrity": "sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg==", + "bundled": true, "requires": { "es6-promisify": "^5.0.0" } @@ -5437,13 +5448,11 @@ }, "sorted-object": { "version": "2.0.1", - "resolved": false, - "integrity": "sha1-fWMfS9OnmKJK8d/8+/6DM3pd9fw=" + "bundled": true }, "sorted-union-stream": { "version": "2.1.3", - "resolved": false, - "integrity": "sha1-x3lMfgd4gAUv9xqNSi27Sppjisc=", + "bundled": true, "requires": { "from2": "^1.3.0", "stream-iterate": "^1.1.0" @@ -5451,8 +5460,7 @@ "dependencies": { "from2": { "version": "1.3.0", - "resolved": false, - "integrity": "sha1-iEE7qqX5pZfP3pIh2GmGzTwGHf0=", + "bundled": true, "requires": { "inherits": "~2.0.1", "readable-stream": "~1.1.10" @@ -5460,13 +5468,11 @@ }, "isarray": { "version": "0.0.1", - "resolved": false, - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + "bundled": true }, "readable-stream": { "version": "1.1.14", - "resolved": false, - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "bundled": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.1", @@ -5476,15 +5482,13 @@ }, "string_decoder": { "version": "0.10.31", - "resolved": false, - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "bundled": true } } }, "spdx-correct": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", + "bundled": true, "requires": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" @@ -5492,13 +5496,11 @@ }, "spdx-exceptions": { "version": "2.1.0", - "resolved": false, - "integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" + "bundled": true }, "spdx-expression-parse": { "version": "3.0.0", - "resolved": false, - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "bundled": true, "requires": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" @@ -5506,18 +5508,15 @@ }, "spdx-license-ids": { "version": "3.0.3", - "resolved": false, - "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==" + "bundled": true }, "split-on-first": { "version": "1.1.0", - "resolved": false, - "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" + "bundled": true }, "sshpk": { "version": "1.14.2", - "resolved": false, - "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", + "bundled": true, "requires": { "asn1": "~0.2.3", "assert-plus": "^1.0.0", @@ -5532,16 +5531,14 @@ }, "ssri": { "version": "6.0.1", - "resolved": false, - "integrity": "sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==", + "bundled": true, "requires": { "figgy-pudding": "^3.5.1" } }, "stream-each": { "version": "1.2.2", - "resolved": false, - "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", + "bundled": true, "requires": { "end-of-stream": "^1.1.0", "stream-shift": "^1.0.0" @@ -5549,8 +5546,7 @@ }, "stream-iterate": { "version": "1.2.0", - "resolved": false, - "integrity": "sha1-K9fHcpbBcCpGSIuK1B95hl7s1OE=", + "bundled": true, "requires": { "readable-stream": "^2.1.5", "stream-shift": "^1.0.0" @@ -5558,8 +5554,7 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5572,8 +5567,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "requires": { "safe-buffer": "~5.1.0" } @@ -5582,18 +5576,15 @@ }, "stream-shift": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=" + "bundled": true }, "strict-uri-encode": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=" + "bundled": true }, "string-width": { "version": "2.1.1", - "resolved": false, - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "bundled": true, "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" @@ -5601,18 +5592,15 @@ "dependencies": { "ansi-regex": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + "bundled": true }, "is-fullwidth-code-point": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "bundled": true }, "strip-ansi": { "version": "4.0.0", - "resolved": false, - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "bundled": true, "requires": { "ansi-regex": "^3.0.0" } @@ -5620,48 +5608,47 @@ } }, "string_decoder": { - "version": "1.2.0", - "resolved": false, - "integrity": "sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==", + "version": "1.3.0", + "bundled": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "~5.2.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.2.0", + "bundled": true + } } }, "stringify-package": { "version": "1.0.1", - "resolved": false, - "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==" + "bundled": true }, "strip-ansi": { "version": "3.0.1", - "resolved": false, - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "bundled": true, "requires": { "ansi-regex": "^2.0.0" } }, "strip-eof": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + "bundled": true }, "strip-json-comments": { "version": "2.0.1", - "resolved": false, - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + "bundled": true }, "supports-color": { "version": "5.4.0", - "resolved": false, - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "bundled": true, "requires": { "has-flag": "^3.0.0" } }, "tar": { "version": "4.4.13", - "resolved": false, - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "bundled": true, "requires": { "chownr": "^1.1.1", "fs-minipass": "^1.2.5", @@ -5674,8 +5661,7 @@ "dependencies": { "minipass": { "version": "2.9.0", - "resolved": false, - "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "bundled": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -5685,26 +5671,22 @@ }, "term-size": { "version": "1.2.0", - "resolved": false, - "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "bundled": true, "requires": { "execa": "^0.7.0" } }, "text-table": { "version": "0.2.0", - "resolved": false, - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" + "bundled": true }, "through": { "version": "2.3.8", - "resolved": false, - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "bundled": true }, "through2": { "version": "2.0.3", - "resolved": false, - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "bundled": true, "requires": { "readable-stream": "^2.1.5", "xtend": "~4.0.1" @@ -5712,8 +5694,7 @@ "dependencies": { "readable-stream": { "version": "2.3.6", - "resolved": false, - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "bundled": true, "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -5726,8 +5707,7 @@ }, "string_decoder": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "bundled": true, "requires": { "safe-buffer": "~5.1.0" } @@ -5736,18 +5716,15 @@ }, "timed-out": { "version": "4.0.1", - "resolved": false, - "integrity": "sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8=" + "bundled": true }, "tiny-relative-date": { "version": "1.3.0", - "resolved": false, - "integrity": "sha512-MOQHpzllWxDCHHaDno30hhLfbouoYlOI8YlMNtvKe1zXbjEVhbcEovQxvZrPvtiYW630GQDoMMarCnjfyfHA+A==" + "bundled": true }, "tough-cookie": { "version": "2.4.3", - "resolved": false, - "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "bundled": true, "requires": { "psl": "^1.1.24", "punycode": "^1.4.1" @@ -5755,71 +5732,60 @@ }, "tunnel-agent": { "version": "0.6.0", - "resolved": false, - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "bundled": true, "requires": { "safe-buffer": "^5.0.1" } }, "tweetnacl": { "version": "0.14.5", - "resolved": false, - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "bundled": true, "optional": true }, "typedarray": { "version": "0.0.6", - "resolved": false, - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" + "bundled": true }, "uid-number": { "version": "0.0.6", - "resolved": false, - "integrity": "sha1-DqEOgDXo61uOREnwbaHHMGY7qoE=" + "bundled": true }, "umask": { "version": "1.1.0", - "resolved": false, - "integrity": "sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0=" + "bundled": true }, "unique-filename": { "version": "1.1.1", - "resolved": false, - "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "bundled": true, "requires": { "unique-slug": "^2.0.0" } }, "unique-slug": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", + "bundled": true, "requires": { "imurmurhash": "^0.1.4" } }, "unique-string": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo=", + "bundled": true, "requires": { "crypto-random-string": "^1.0.0" } }, "unpipe": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + "bundled": true }, "unzip-response": { "version": "2.0.1", - "resolved": false, - "integrity": "sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c=" + "bundled": true }, "update-notifier": { "version": "2.5.0", - "resolved": false, - "integrity": "sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw==", + "bundled": true, "requires": { "boxen": "^1.2.1", "chalk": "^2.0.1", @@ -5835,39 +5801,33 @@ }, "url-parse-lax": { "version": "1.0.0", - "resolved": false, - "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "bundled": true, "requires": { "prepend-http": "^1.0.1" } }, "util-deprecate": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + "bundled": true }, "util-extend": { "version": "1.0.3", - "resolved": false, - "integrity": "sha1-p8IW0mdUUWljeztu3GypEZ4v+T8=" + "bundled": true }, "util-promisify": { "version": "2.1.0", - "resolved": false, - "integrity": "sha1-PCI2R2xNMsX/PEcAKt18E7moKlM=", + "bundled": true, "requires": { "object.getownpropertydescriptors": "^2.0.3" } }, "uuid": { "version": "3.3.3", - "resolved": false, - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + "bundled": true }, "validate-npm-package-license": { "version": "3.0.4", - "resolved": false, - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "bundled": true, "requires": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" @@ -5875,16 +5835,14 @@ }, "validate-npm-package-name": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-X6kS2B630MdK/BQN5zF/DKffQ34=", + "bundled": true, "requires": { "builtins": "^1.0.3" } }, "verror": { "version": "1.10.0", - "resolved": false, - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "bundled": true, "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -5893,37 +5851,32 @@ }, "wcwidth": { "version": "1.0.1", - "resolved": false, - "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "bundled": true, "requires": { "defaults": "^1.0.3" } }, "which": { "version": "1.3.1", - "resolved": false, - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "bundled": true, "requires": { "isexe": "^2.0.0" } }, "which-module": { "version": "2.0.0", - "resolved": false, - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + "bundled": true }, "wide-align": { "version": "1.1.2", - "resolved": false, - "integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==", + "bundled": true, "requires": { "string-width": "^1.0.2" }, "dependencies": { "string-width": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5933,25 +5886,22 @@ } }, "widest-line": { - "version": "2.0.0", - "resolved": false, - "integrity": "sha1-AUKk6KJD+IgsAjOqDgKBqnYVInM=", + "version": "2.0.1", + "bundled": true, "requires": { "string-width": "^2.1.1" } }, "worker-farm": { "version": "1.7.0", - "resolved": false, - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "bundled": true, "requires": { "errno": "~0.1.7" } }, "wrap-ansi": { "version": "2.1.0", - "resolved": false, - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "bundled": true, "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" @@ -5959,8 +5909,7 @@ "dependencies": { "string-width": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "bundled": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -5971,13 +5920,11 @@ }, "wrappy": { "version": "1.0.2", - "resolved": false, - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "bundled": true }, "write-file-atomic": { "version": "2.4.3", - "resolved": false, - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "bundled": true, "requires": { "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", @@ -5986,34 +5933,29 @@ }, "xdg-basedir": { "version": "3.0.0", - "resolved": false, - "integrity": "sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ=" + "bundled": true }, "xtend": { "version": "4.0.1", - "resolved": false, - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + "bundled": true }, "y18n": { "version": "4.0.0", - "resolved": false, - "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==" + "bundled": true }, "yallist": { "version": "3.0.3", - "resolved": false, - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + "bundled": true }, "yargs": { - "version": "11.0.0", - "resolved": false, - "integrity": "sha512-Rjp+lMYQOWtgqojx1dEWorjCofi1YN7AoFvYV7b1gx/7dAAeuI4kN5SZiEvr0ZmsZTOpDRcCqrpI10L31tFkBw==", + "version": "11.1.1", + "bundled": true, "requires": { "cliui": "^4.0.0", "decamelize": "^1.1.1", "find-up": "^2.1.0", "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", + "os-locale": "^3.1.0", "require-directory": "^2.1.1", "require-main-filename": "^1.0.1", "set-blocking": "^2.0.0", @@ -6025,15 +5967,13 @@ "dependencies": { "y18n": { "version": "3.2.1", - "resolved": false, - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + "bundled": true } } }, "yargs-parser": { "version": "9.0.2", - "resolved": false, - "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", + "bundled": true, "requires": { "camelcase": "^4.1.0" } @@ -6048,60 +5988,98 @@ "boolbase": "~1.0.0" } }, - "nwmatcher": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.4.tgz", - "integrity": "sha512-3iuY4N5dhgMpCUrOVnuAdGrgxVqV2cJpM+XNccjR2DKOB1RUP0aA+wGXEiNziG/UKboFyGBIoKOaNlJxx8bciQ==", - "optional": true - }, "nyc": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-14.1.0.tgz", - "integrity": "sha512-iy9fEV8Emevz3z/AanIZsoGa8F4U2p0JKevZ/F0sk+/B2r9E6Qn+EPs0bpxEhnAt6UPlTL8mQZIaSJy8sK0ZFw==", + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.0.0.tgz", + "integrity": "sha512-qcLBlNCKMDVuKb7d1fpxjPR8sHeMVX0CHarXAVzrVWoFrigCkYR8xcrjfXSPi5HXM7EU78L6ywO7w1c5rZNCNg==", "dev": true, "requires": { - "archy": "^1.0.0", - "caching-transform": "^3.0.2", - "convert-source-map": "^1.6.0", - "cp-file": "^6.2.0", - "find-cache-dir": "^2.1.0", - "find-up": "^3.0.0", - "foreground-child": "^1.5.6", - "glob": "^7.1.3", - "istanbul-lib-coverage": "^2.0.5", - "istanbul-lib-hook": "^2.0.7", - "istanbul-lib-instrument": "^3.3.0", - "istanbul-lib-report": "^2.0.8", - "istanbul-lib-source-maps": "^3.0.6", - "istanbul-reports": "^2.2.4", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "caching-transform": "^4.0.0", + "convert-source-map": "^1.7.0", + "decamelize": "^1.2.0", + "find-cache-dir": "^3.2.0", + "find-up": "^4.1.0", + "foreground-child": "^2.0.0", + "glob": "^7.1.6", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-hook": "^3.0.0", + "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-processinfo": "^2.0.2", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.0.0", "js-yaml": "^3.13.1", - "make-dir": "^2.1.0", - "merge-source-map": "^1.1.0", - "resolve-from": "^4.0.0", - "rimraf": "^2.6.3", + "make-dir": "^3.0.0", + "node-preload": "^0.2.0", + "p-map": "^3.0.0", + "process-on-spawn": "^1.0.0", + "resolve-from": "^5.0.0", + "rimraf": "^3.0.0", "signal-exit": "^3.0.2", - "spawn-wrap": "^1.4.2", - "test-exclude": "^5.2.3", - "uuid": "^3.3.2", - "yargs": "^13.2.2", - "yargs-parser": "^13.0.0" + "spawn-wrap": "^2.0.0", + "test-exclude": "^6.0.0", + "uuid": "^3.3.3", + "yargs": "^15.0.2" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", "dev": true }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "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 + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, "glob": { @@ -6118,31 +6096,94 @@ "path-is-absolute": "^1.0.0" } }, + "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 + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "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" + } + }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "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": "^4.1.0" + "ansi-regex": "^5.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" } }, "yargs": { - "version": "13.3.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", - "integrity": "sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA==", + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", "dev": true, "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^3.0.0", + "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^13.1.1" + "yargs-parser": "^18.1.1" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" } } } @@ -6152,11 +6193,6 @@ "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" }, - "object-assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", - "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=" - }, "object-component": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz", @@ -6165,22 +6201,35 @@ "object-inspect": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "dev": true }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, - "object.values": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz", - "integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==", + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.12.0", + "define-properties": "^1.1.2", "function-bind": "^1.1.1", - "has": "^1.0.3" + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", + "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" } }, "on-finished": { @@ -6205,45 +6254,53 @@ "wrappy": "1" } }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, + "openapi-backend": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/openapi-backend/-/openapi-backend-2.4.1.tgz", + "integrity": "sha512-48j8QhDD9sfV6t7Zgn9JrfJtCpJ53bmoT2bzXYYig1HhG/Xn0Aa5fJhM0cQSZq9nq78/XbU7RDEa3e+IADNkmA==", + "requires": { + "ajv": "^6.10.0", + "bath-es5": "^3.0.3", + "cookie": "^0.4.0", + "lodash": "^4.17.15", + "mock-json-schema": "^1.0.5", + "openapi-schema-validation": "^0.4.2", + "openapi-types": "^1.3.4", + "qs": "^6.6.0", + "swagger-parser": "^9.0.1" + }, + "dependencies": { + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + } + } + }, + "openapi-schema-validation": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/openapi-schema-validation/-/openapi-schema-validation-0.4.2.tgz", + "integrity": "sha512-K8LqLpkUf2S04p2Nphq9L+3bGFh/kJypxIG2NVGKX0ffzT4NQI9HirhiY6Iurfej9lCu7y4Ndm4tv+lm86Ck7w==", "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" + "jsonschema": "1.2.4", + "jsonschema-draft4": "^1.0.0", + "swagger-schema-official": "2.0.0-bab6bed" } }, + "openapi-types": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-1.3.5.tgz", + "integrity": "sha512-11oi4zYorsgvg5yBarZplAqbpev5HkuVNPlZaPTknPDzAynq+lnJdXAmruGWP0s+dNYZS7bjM+xrTpJw7184Fg==" + }, "optional-js": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/optional-js/-/optional-js-2.1.1.tgz", "integrity": "sha512-mUS4bDngcD5kKzzRUd1HVQkr9Lzzby3fSrrPR9wOHhQiyYo+hDS5NVli5YQzGjQRQ15k5Sno4xH9pfykJdeEUA==" }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "optional": true, - "requires": { - "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" - } - }, - "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 - }, "p-limit": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.1.tgz", - "integrity": "sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "requires": { "p-try": "^2.0.0" @@ -6258,6 +6315,15 @@ "p-limit": "^2.0.0" } }, + "p-map": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", + "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", + "dev": true, + "requires": { + "aggregate-error": "^3.0.0" + } + }, "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", @@ -6265,37 +6331,21 @@ "dev": true }, "package-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-3.0.0.tgz", - "integrity": "sha512-lOtmukMDVvtkL84rJHI7dpTYq+0rli8N2wlnqUcBuDWCfVhRUfOmnR9SsoHFMLpACvEV60dX7rd0rFaYDZI+FA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", + "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", "dev": true, "requires": { "graceful-fs": "^4.1.15", - "hasha": "^3.0.0", + "hasha": "^5.0.0", "lodash.flattendeep": "^4.4.0", "release-zalgo": "^1.0.0" } }, "packet-reader": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.2.0.tgz", - "integrity": "sha1-gZ300BC4LV6lZx+KGjrPA5vNdwA=" - }, - "parse-json": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", - "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", - "dev": true, - "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" - } - }, - "parse5": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", - "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", - "optional": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" }, "parseqs": { "version": "0.0.5", @@ -6330,6 +6380,12 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, "path-parse": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", @@ -6341,39 +6397,22 @@ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, - "path-type": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", - "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", - "dev": true, - "requires": { - "pify": "^3.0.0" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, "performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" }, "pg": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/pg/-/pg-6.1.6.tgz", - "integrity": "sha1-3SJ1glDVrW7vWiv4jZbydtHpWw0=", + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/pg/-/pg-7.18.2.tgz", + "integrity": "sha512-Mvt0dGYMwvEADNKy5PMQGlzPudKcKKzJds/VbOeZJpb6f/pI3mmoXX0JksPgI3l3JPP/2Apq7F36O63J7mgveA==", "requires": { - "buffer-writer": "1.0.1", - "js-string-escape": "1.0.1", - "packet-reader": "0.2.0", + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", - "pg-pool": "1.*", - "pg-types": "1.*", + "pg-packet-stream": "^1.1.0", + "pg-pool": "^2.0.10", + "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" }, @@ -6395,24 +6434,25 @@ "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" }, + "pg-packet-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pg-packet-stream/-/pg-packet-stream-1.1.0.tgz", + "integrity": "sha512-kRBH0tDIW/8lfnnOyTwKD23ygJ/kexQVXZs7gEyBljw4FYqimZFxnMMx50ndZ8In77QgfGuItS5LLclC2TtjYg==" + }, "pg-pool": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-1.8.0.tgz", - "integrity": "sha1-9+xzgkw3oD8Hb1G/33DjQBR8Tzc=", - "requires": { - "generic-pool": "2.4.3", - "object-assign": "4.1.0" - } + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.10.tgz", + "integrity": "sha512-qdwzY92bHf3nwzIUcj+zJ0Qo5lpG/YxchahxIN8+ZVmXqkahKXsnl2aiJPHLYN9o5mB/leG+Xh6XKxtP7e0sjg==" }, "pg-types": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.13.0.tgz", - "integrity": "sha512-lfKli0Gkl/+za/+b6lzENajczwZHc7D5kiUCZfgm914jipD2kIOIvEkAhZ8GrW3/TUoP9w8FHjwpPObBye5KQQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", "requires": { "pg-int8": "1.0.1", - "postgres-array": "~1.0.0", + "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.0", + "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, @@ -6424,25 +6464,61 @@ "split": "^1.0.0" } }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", "dev": true }, "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "requires": { - "find-up": "^3.0.0" + "find-up": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + } } }, "postgres-array": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.3.tgz", - "integrity": "sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" }, "postgres-bytea": { "version": "1.0.0", @@ -6450,9 +6526,9 @@ "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" }, "postgres-date": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.4.tgz", - "integrity": "sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA==" + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.5.tgz", + "integrity": "sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA==" }, "postgres-interval": { "version": "1.2.0", @@ -6462,16 +6538,19 @@ "xtend": "^4.0.0" } }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "optional": true - }, "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "process-on-spawn": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", + "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", + "dev": true, + "requires": { + "fromentries": "^1.2.0" + } }, "promise": { "version": "1.3.0", @@ -6482,24 +6561,18 @@ } }, "proxy-addr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.5.tgz", - "integrity": "sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", "requires": { "forwarded": "~0.1.2", - "ipaddr.js": "1.9.0" + "ipaddr.js": "1.9.1" } }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, "psl": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", - "integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==" + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" }, "punycode": { "version": "2.1.1", @@ -6513,9 +6586,9 @@ "dev": true }, "qs": { - "version": "6.5.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", - "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, "random-bytes": { "version": "1.0.0", @@ -6536,48 +6609,55 @@ "http-errors": "1.7.2", "iconv-lite": "0.4.24", "unpipe": "1.0.0" + }, + "dependencies": { + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + } } }, - "read-pkg": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", - "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", - "dev": true, + "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==", "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" } }, - "read-pkg-up": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-4.0.0.tgz", - "integrity": "sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA==", + "readdirp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", + "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", "dev": true, "requires": { - "find-up": "^3.0.0", - "read-pkg": "^3.0.0" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "picomatch": "^2.0.4" } }, "redis": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", - "integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.0.2.tgz", + "integrity": "sha512-PNhLCrjU6vKVuMOyFu7oSP296mwBkcE6lrAjruBYG5LgdSqtRBoVQIylrMyVZD/lkF24RSNNatzvYag6HRBHjQ==", "requires": { - "double-ended-queue": "^2.1.0-0", - "redis-commands": "^1.2.0", - "redis-parser": "^2.6.0" + "denque": "^1.4.1", + "redis-commands": "^1.5.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" } }, "redis-commands": { @@ -6585,10 +6665,18 @@ "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz", "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg==" }, + "redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60=" + }, "redis-parser": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", - "integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=", + "requires": { + "redis-errors": "^1.0.0" + } }, "release-zalgo": { "version": "1.0.0", @@ -6599,11 +6687,6 @@ "es6-error": "^4.0.1" } }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" - }, "request": { "version": "2.88.0", "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", @@ -6631,19 +6714,10 @@ "uuid": "^3.3.2" }, "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" - }, - "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==", - "requires": { - "psl": "^1.1.24", - "punycode": "^1.4.1" - } + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" } } }, @@ -6665,52 +6739,28 @@ "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=" }, "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==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, "rethinkdb": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/rethinkdb/-/rethinkdb-2.3.3.tgz", - "integrity": "sha1-PcZYbiL6HavuDSVOZL0ON5+tL3I=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/rethinkdb/-/rethinkdb-2.4.2.tgz", + "integrity": "sha512-6DzwqEpFc8cqesAdo07a845oBRxLiHvWzopTKBo/uY2ypGWIsJQFJk3wjRDtSEhczxJqLS0jnf37rwgzYAw8NQ==", "requires": { "bluebird": ">= 2.3.2 < 3" } }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "requires": { - "align-text": "^0.1.1" - } - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "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" - } - } - } - }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, "safe-buffer": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", @@ -6721,12 +6771,6 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", - "optional": true - }, "security": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/security/-/security-1.0.0.tgz", @@ -6786,10 +6830,25 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", "dev": true }, "slide": { @@ -6821,9 +6880,9 @@ } }, "socket.io-adapter": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.1.tgz", - "integrity": "sha1-KoBeihTWNyEk3ZFZrUUC+MsH8Gs=" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", + "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" }, "socket.io-client": { "version": "2.1.1", @@ -6887,51 +6946,30 @@ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "spawn-wrap": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-1.4.3.tgz", - "integrity": "sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", + "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", "dev": true, "requires": { - "foreground-child": "^1.5.6", - "mkdirp": "^0.5.0", - "os-homedir": "^1.0.1", - "rimraf": "^2.6.2", + "foreground-child": "^2.0.0", + "is-windows": "^1.0.2", + "make-dir": "^3.0.0", + "rimraf": "^3.0.0", "signal-exit": "^3.0.2", - "which": "^1.3.0" - } - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "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 - }, - "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, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, - "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 - }, "split": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", @@ -6943,13 +6981,12 @@ "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, "sqlstring": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.0.tgz", - "integrity": "sha1-UluKT9Jtb3GqYegipsr5dtMa0qg=" + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" }, "sshpk": { "version": "1.16.1", @@ -6973,55 +7010,81 @@ "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" }, "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==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "strip-ansi": "^4.0.0" }, "dependencies": { "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", "dev": true }, "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^3.0.0" } } } }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, "string.prototype.trimleft": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz", - "integrity": "sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", + "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", + "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5", + "string.prototype.trimstart": "^1.0.0" } }, "string.prototype.trimright": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz", - "integrity": "sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz", + "integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==", + "dev": true, "requires": { "define-properties": "^1.1.3", - "function-bind": "^1.1.1" + "es-abstract": "^1.17.5", + "string.prototype.trimend": "^1.0.0" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" } }, "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + "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==", + "requires": { + "safe-buffer": "~5.2.0" + } }, "strip-ansi": { "version": "3.0.1", @@ -7032,9 +7095,15 @@ } }, "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, "superagent": { @@ -7076,16 +7145,10 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -7115,13 +7178,13 @@ } }, "supertest": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/supertest/-/supertest-3.0.0.tgz", - "integrity": "sha1-jUu2j9GDDuBwM7HFpamkAhyWUpY=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-4.0.2.tgz", + "integrity": "sha512-1BAbvrOZsGA3YTCWqbmh14L0YEq0EGICX/nBnfkfVJn7SrxQV1I3pMYjSzG9y/7ZU2V9dWqyqk2POwxlb09duQ==", "dev": true, "requires": { - "methods": "~1.1.2", - "superagent": "^3.0.0" + "methods": "^1.1.2", + "superagent": "^3.8.3" } }, "supports-color": { @@ -7129,72 +7192,41 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" }, - "swagger-node-express": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/swagger-node-express/-/swagger-node-express-2.1.3.tgz", - "integrity": "sha1-Sx/ul24RKE0nZXWRGYCyJY43nas=", + "swagger-parser": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-9.0.1.tgz", + "integrity": "sha512-oxOHUaeNetO9ChhTJm2fD+48DbGbLD09ZEOwPOWEqcW8J6zmjWxutXtSuOiXsoRgDWvORYlImbwM21Pn+EiuvQ==", "requires": { - "lodash": "1.3.1" - }, - "dependencies": { - "lodash": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.3.1.tgz", - "integrity": "sha1-pGY7U2hriV/wdOK6UE37dqjit3A=" - } + "@apidevtools/swagger-parser": "9.0.1" } }, - "symbol-tree": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", - "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "optional": true + "swagger-schema-official": { + "version": "2.0.0-bab6bed", + "resolved": "https://registry.npmjs.org/swagger-schema-official/-/swagger-schema-official-2.0.0-bab6bed.tgz", + "integrity": "sha1-cAcEaNbSl3ylI3suUZyn0Gouo/0=" }, "tar-stream": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.0.tgz", - "integrity": "sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.1.2.tgz", + "integrity": "sha512-UaF6FoJ32WqALZGOIAApXx+OdxhekNMChu6axLJR85zMMjXKWFGjbIRe+J6P4UnRGg9rAwWvbTT0oI7hD/Un7Q==", "dev": true, "requires": { - "bl": "^3.0.0", + "bl": "^4.0.1", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" - }, - "dependencies": { - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "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" - } - } } }, "test-exclude": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-5.2.3.tgz", - "integrity": "sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", "dev": true, "requires": { - "glob": "^7.1.3", - "minimatch": "^3.0.4", - "read-pkg-up": "^4.0.0", - "require-main-filename": "^2.0.0" + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" }, "dependencies": { "glob": { @@ -7234,27 +7266,36 @@ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", "dev": true }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, "tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", - "optional": true, + "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==", "requires": { - "psl": "^1.1.28", - "punycode": "^2.1.1" + "psl": "^1.1.24", + "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + } } }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", - "optional": true - }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -7268,14 +7309,11 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "optional": true, - "requires": { - "prelude-ls": "~1.1.2" - } + "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 }, "type-is": { "version": "1.6.18", @@ -7286,58 +7324,48 @@ "mime-types": "~2.1.24" } }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, "ueberdb2": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/ueberdb2/-/ueberdb2-0.4.0.tgz", - "integrity": "sha512-iY4+J8D+S5OP6dP9bSomJfN7zIZMcsO8h7J+EsxXod+iUpnQXmIIYsb9+Ui1Fz4KFiGbMDSaDP6Ipqz/l/1hmA==", + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/ueberdb2/-/ueberdb2-0.4.5.tgz", + "integrity": "sha512-D8TogZ6Dc4Ot909b0D0QQRSanVB3W4EtqA8smKEZS7H5eIbAWFOyBF74XADIB9f+NASSjdu8DU3EJeKe9Xdzjg==", "requires": { - "async": "0.1.15", - "cassandra-driver": "2.0.1", + "async": "^3.2.0", + "cassandra-driver": "^4.5.0", "channels": "0.0.4", - "dirty": "0.9.x", - "elasticsearch": "15.1.1", - "mysql": "2.15.0", - "nano": "^6.2.0", - "pg": "~6.1.6", + "dirty": "^1.1.0", + "elasticsearch": "^16.7.1", + "mysql": "2.18.1", + "nano": "^8.2.2", + "pg": "^7.18.2", "redis": ">=0.12.1", "rethinkdb": "^2.3.1" }, "dependencies": { "async": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/async/-/async-0.1.15.tgz", - "integrity": "sha1-IYDqyizypspSgNQcBYW+ybPkm9M=" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz", + "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==" } } }, "uglify-js": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.2.tgz", - "integrity": "sha1-9QvoikLNOWpiUdxSqzcvccwS/vA=", - "requires": { - "async": "~0.2.6", - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" - }, - "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" - } + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.8.1.tgz", + "integrity": "sha512-W7KxyzeaQmZvUFbGj4+YFshhVrMBGSg2IbcYAjGWGvx8DHvJMclbTDMpffdxFUGPBHjIytk7KJUR/KUXstUGDw==", + "requires": { + "commander": "~2.20.3", + "source-map": "~0.6.1" } }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=" - }, "uid-safe": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", @@ -7385,19 +7413,14 @@ "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" }, "uuid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", - "integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" }, - "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, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } + "validator": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-12.2.0.tgz", + "integrity": "sha512-jJfE/DW6tIK1Ek8nCfNFqt8Wb3nzMoAbocBF6/Icgg1ZFSBpObdnwVY2jQj6qUqzhx5jc71fpvBWyLGO7Xl+nQ==" }, "vargs": { "version": "0.1.0", @@ -7446,21 +7469,6 @@ } } }, - "webidl-conversions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-2.0.1.tgz", - "integrity": "sha1-O/glj30xjHRDw28uFpQCoaZwNQY=", - "optional": true - }, - "whatwg-url-compat": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/whatwg-url-compat/-/whatwg-url-compat-0.6.5.tgz", - "integrity": "sha1-AImBEa9om7CXVBzVpFymyHmERb8=", - "optional": true, - "requires": { - "tr46": "~0.0.1" - } - }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -7476,21 +7484,14 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" - }, - "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==", - "optional": true - }, - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "dev": true, + "requires": { + "string-width": "^1.0.2 || 2" + } }, "wrap-ansi": { "version": "5.1.0", @@ -7518,6 +7519,17 @@ "color-convert": "^1.9.0" } }, + "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, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, "strip-ansi": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", @@ -7536,14 +7548,15 @@ "dev": true }, "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" } }, "ws": { @@ -7563,12 +7576,6 @@ } } }, - "xml-name-validator": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-2.0.1.tgz", - "integrity": "sha1-TYuPHszTQZqjYgYb7O9RXh5VljU=", - "optional": true - }, "xmlhttprequest-ssl": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz", @@ -7585,39 +7592,71 @@ "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "dev": true }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - }, "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", - "window-size": "0.1.0" + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "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 + }, + "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, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.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" + } + } } }, "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - } + } + }, + "yargs-unparser": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", + "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "dev": true, + "requires": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" } }, "yeast": { @@ -7625,37 +7664,26 @@ "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" }, + "z-schema": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-4.2.3.tgz", + "integrity": "sha512-zkvK/9TC6p38IwcrbnT3ul9in1UX4cm1y/VZSs4GHKIiDCrlafc+YQBgQBUdDXLAoZHf2qvQ7gJJOo6yT1LH6A==", + "requires": { + "commander": "^2.7.1", + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^12.0.0" + } + }, "zip-stream": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.2.tgz", - "integrity": "sha512-ykebHGa2+uzth/R4HZLkZh3XFJzivhVsjJt8bN3GvBzLaqqrUdRacu+c4QtnUgjkkQfsOuNE1JgLKMCPNmkKgg==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-2.1.3.tgz", + "integrity": "sha512-EkXc2JGcKhO5N5aZ7TmuNo45budRaFGHOmz24wtJR7znbNqDPmdZtUauKX6et8KAVseAMBOyWJqEpXcHTBsh7Q==", "dev": true, "requires": { "archiver-utils": "^2.1.0", "compress-commons": "^2.1.1", "readable-stream": "^3.4.0" - }, - "dependencies": { - "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "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" - } - } } } } diff --git a/src/package.json b/src/package.json index 8a8edd3e839..5632ab61855 100644 --- a/src/package.json +++ b/src/package.json @@ -33,34 +33,36 @@ "async": "0.9.0", "async-stacktrace": "0.0.2", "channels": "0.0.4", - "cheerio": "0.20.0", - "clean-css": "3.4.19", + "cheerio": "0.22.0", + "clean-css": "4.2.3", "cookie-parser": "1.4.4", "ejs": "2.6.1", "etherpad-require-kernel": "1.0.9", "etherpad-yajsml": "0.0.2", "express": "4.17.1", + "express-rate-limit": "5.1.1", "express-session": "1.17.0", "find-root": "1.1.0", "formidable": "1.2.1", "graceful-fs": "4.2.2", + "http-errors": "1.7.3", "jsonminify": "0.4.1", "languages4translatewiki": "0.1.3", + "lodash.clonedeep": "4.5.0", "log4js": "0.6.35", "measured-core": "1.11.2", - "nodeify": "^1.0.1", - "npm": "6.13.1", - "object.values": "^1.0.4", + "nodeify": "1.0.1", + "npm": "6.14.4", + "openapi-backend": "2.4.1", "request": "2.88.0", "resolve": "1.1.7", "security": "1.0.0", "semver": "5.6.0", "slide": "1.1.6", "socket.io": "2.1.1", - "swagger-node-express": "2.1.3", "tinycon": "0.0.1", - "ueberdb2": "0.4.0", - "uglify-js": "2.6.2", + "ueberdb2": "0.4.5", + "uglify-js": "3.8.1", "underscore": "1.8.3", "unorm": "1.4.1" }, @@ -68,13 +70,13 @@ "etherpad-lite": "./node/server.js" }, "devDependencies": { - "mocha": "5.2.0", - "nyc": "14.1.0", - "supertest": "3.0.0", + "mocha": "7.1.1", + "nyc": "15.0.0", + "supertest": "4.0.2", "wd": "1.11.4" }, "engines": { - "node": ">=8.9.0", + "node": ">=10.13.0", "npm": ">=5.5.1" }, "repository": { @@ -82,8 +84,9 @@ "url": "https://github.com/ether/etherpad-lite.git" }, "scripts": { - "test": "nyc mocha --timeout 5000 ../tests/backend/specs/api" + "test": "nyc mocha --timeout 5000 ../tests/backend/specs/api", + "test-container": "nyc mocha --timeout 5000 ../tests/container/specs/api" }, - "version": "1.8.0", + "version": "1.8.3", "license": "Apache-2.0" } diff --git a/src/static/css/iframe_editor.css b/src/static/css/iframe_editor.css index 9aa003aaf73..12f5d1c5c20 100644 --- a/src/static/css/iframe_editor.css +++ b/src/static/css/iframe_editor.css @@ -1,46 +1,63 @@ -/* These CSS rules are included in both the outer and inner ACE iframe. - Also see inner.css, included only in the inner one. +/* + These CSS rules are included in both the outer and inner ACE iframe (pad editor) */ @import url('./lists_and_indents.css'); -html { cursor: text; } /* in Safari, produces text cursor for whole doc (inc. below body) */ -span { cursor: auto; } +html.inner-editor { + height: auto !important; + background-color: transparent !important; +} +#outerdocbody { + display: flex; + flex-direction: row; + justify-content: center; + min-height: 100vh; /* take at least full height */ +} +#outerdocbody iframe { + flex: 1 auto; + display: flex; + width: 100%; +} +#outerdocbody #sidediv { + order: -1; /* display it on the first row positionning, i.e. on the left */ +} -::selection { - background: #acf; +/* ACE-PAD Container (i.e. where the text is displayed) */ +#innerdocbody { + padding: 10px; + overflow: hidden; + background-color: white; } -::-moz-selection { - background: #acf; +#innerdocbody, #sidediv { + padding-top: 10px; /* Both must have same top padding, so line number are aligned with the rows */ + padding-bottom: 10px; /* some space when we scroll to the bottom */ } -a { - cursor: pointer !important; - white-space:pre-wrap; +/* --------------------- */ +/* -- BROWSER SUPPORT -- */ +/* --------------------- */ + +body.mozilla, body.safari { + display: table-cell; /* cause "body" area (e.g. where clicks are heard) to grow horizontally with text */ +} +.safari div { + padding-right: 1px; /* prevents the caret from disappearing on the longest line of the doc */ } +span { line-height: 125%; } + + +/* -------------- */ +/* -- WRAPPING -- */ +/* -------------- */ body { - margin: 0; white-space: nowrap; word-wrap: normal; } - -#outerdocbody { - background-color: #fff; -} -body.grayedout { background-color: #eee !important } - -#innerdocbody { - font-size: 12px; /* overridden by body.style */ - font-family:Arial, sans-serif; /* overridden by body.style */ - line-height: 16px; /* overridden by body.style */ - background-color: white; - color: black; -} - body.doesWrap { + display: block !important; /* white-space: pre-wrap; */ - /* Must be pre-wrap to keep trailing spaces. Otherwise you get a zombie caret, walking around your screen (see #1766). @@ -53,86 +70,41 @@ body.doesWrap { */ word-wrap: break-word; /* fix for issue #1648 - firefox not wrapping long lines (without spaces) correctly */ } - .noprewrap{ white-space: normal; } - -body.doesWrap:not(.noprewrap) > div{ +body.doesWrap:not(.noprewrap) > div { /* Related to #1766 */ white-space: pre-wrap; } -#innerdocbody { - padding-top: 1px; /* important for some reason? */ - padding-right: 10px; - padding-bottom: 8px; - padding-left: 1px /* prevents characters from looking chopped off in FF3 -- Removed because it added too much whitespace */; - overflow: hidden; - /* blank 1x1 gif, so that IE8 doesn't consider the body transparent */ - background-image: url(data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==); -} + +/* ------------------------------------------ */ +/* -- SIDEDIV (line number, text author..) -- */ +/* ------------------------------------------ */ #sidediv { font-size: 11px; font-family: monospace; - line-height: 16px; /* overridden by sideDiv.style */ - padding-top: 8px; /* EDIT_BODY_PADDING_TOP */ - padding-right: 3px; /* LINE_NUMBER_PADDING_RIGHT - 1 */ - position: absolute; - width: 20px; /* MIN_LINEDIV_WIDTH */ - top: 0; - left: 0; - cursor: default; - color: white; + padding-right: 5px; + padding-left: 12px; + background-color: transparent; + border-right: 1px solid #ccc; } - #sidedivinner { text-align: right; + opacity: .9; } - -.sidedivdelayed { /* class set after sizes are set */ - background-color: #eee; - color: #888 !important; - border-right: 1px solid #ccc; -} -.sidedivhidden { - display: none; -} - -#outerdocbody iframe { - display: block; /* codemirror says it suppresses bugs */ - position: relative; - left: 32px; /* MIN_LINEDIV_WIDTH + LINE_NUMBER_PADDING_RIGHT + EDIT_BODY_PADDING_LEFT */ - top: 7px; /* EDIT_BODY_PADDING_TOP - 1*/ - border: 0; - width: 1px; /* changed programmatically */ - height: 1px; /* changed programmatically */ -} - -#outerdocbody .hotrect { - border: 1px solid #999; - position: absolute; -} - -/* cause "body" area (e.g. where clicks are heard) to grow horizontally with text */ -body.mozilla, body.safari { - display: table-cell; +#sidediv:not(.sidedivdelayed) { /* before sidediv get initialized, hide text */ + color: transparent; } - -body.doesWrap { - display: block !important; +#sidediv.sidedivhidden { + /* Do not use display: none to hide the sidediv, otherwise the parent container does not + get its height properly calculated by flexboxes */ + visibility: hidden; + width: 0; + padding: 0; } - -.safari div { - /* prevents the caret from disappearing on the longest line of the doc */ - padding-right: 1px; -} - -p { - margin: 0; -} - #linemetricsdiv { position: absolute; left: -1000px; @@ -142,11 +114,33 @@ p { font-size: 12px; /* overridden by lineMetricsDiv.style */ font-family: monospace; /* overridden by lineMetricsDiv.style */ } +@media (max-width: 720px) { + #sidediv { + /* Do not use display: none to hide the sidediv, otherwise the parent container does not + get its height properly calculated by flexboxes */ + visibility: hidden; + width: 0; + padding: 0; + } +} -/* Stops super long lines without being spaces such as aaaaaaaaaaaaaa*100 breaking the editor - Commented out because it stops IE from being able to render the document, crazy IE bug is crazy. */ -/* -.ace-line{ - overflow:hidden; + + + +/* ----------- */ +/* -- OTHER -- */ +/* ----------- */ + +::selection { + background: #acf; } -*/ +::-moz-selection { + background: #acf; +} +#innerdocbody a { + cursor: pointer !important; + white-space:pre-wrap; +} +body.grayedout { + background-color: #eee !important +} \ No newline at end of file diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 7d598594699..cf89ed35dfc 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -1,1354 +1,77 @@ -*, -html, -body, -p { - margin: 0; - padding: 0px; -} +@import url("pad/normalize.css"); + +@import url("pad/layout.css"); +@import url("pad/fonts.css"); +@import url("pad/toolbar.css"); +@import url("pad/popup.css"); +@import url("pad/popup_connectivity.css"); +@import url("pad/popup_import_export.css"); +@import url("pad/popup_users.css"); +@import url("pad/icons.css"); +@import url("pad/chat.css"); +@import url("pad/gritter.css"); +@import url("pad/loadingbox.css"); +@import url("pad/form.css"); -.clear { - clear: both -} html { - font-size: 62.5%; - width: 100%; -} -body, -textarea { - font-family: Helvetica, Arial, sans-serif -} -iframe { - position: absolute + font-size: 14px; + line-height: 20px; + color: #3e3e3e; } -.readonly .acl-write { - display: none; + +html, +#sidedivinner > div:before { + font-family: Cantarell, Roboto, "Open Sans", "Helvetica Neue", Arial, sans-serif; } -#users { - background: #f7f7f7; - background: -webkit-linear-gradient( #F7F7F7,#EEE); - background: -moz-linear-gradient( #F7F7F7,#EEE); - background: -ms-linear-gradient( #F7F7F7,#EEE); - background: -o-linear-gradient( #F7F7F7,#EEE); - background: linear-gradient( #F7F7F7,#EEE); - width: 160px; - color: #fff; - padding: 5px; - border-radius: 0 0 6px 6px; - border: 1px solid #ccc; +.clear { + clear: both } -#otherusers { - max-height: 400px; - overflow: auto; +a { + color: inherit; } a img { border: 0 } -/* menu */ -.toolbar { - background: #f7f7f7; - background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -moz-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -o-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: linear-gradient(#f7f7f7, #f1f1f1 80%); - border-bottom: 1px solid #ccc; - overflow: hidden; - padding-top: 4px; - width: 100%; - white-space: nowrap; - height: 32px; -} -.toolbar ul { - position: absolute; - list-style: none; - padding-right: 3px; - padding-left: 1px; - z-index: 2; - overflow: hidden; - float: left -} -.toolbar ul li { - float: left; - margin-left: 2px; - height:32px; -} -.toolbar ul li.separator { - border: inherit; - background: inherit; - visibility: hidden; - width: 0px; - padding: 5px; - height:22px; -} -.toolbar ul li a:hover { - text-decoration: none; -} -.toolbar ul li a:hover { - background: #fff; - background: -webkit-linear-gradient(#f4f4f4, #e4e4e4); - background: -moz-linear-gradient(#f4f4f4, #e4e4e4); - background: -o-linear-gradient(#f4f4f4, #e4e4e4); - background: -ms-linear-gradient(#f4f4f4, #e4e4e4); - background: linear-gradient(#f4f4f4, #e4e4e4); -} -.toolbar ul li a:active { - background: #eee; - background: -webkit-linear-gradient(#ddd, #fff); - background: -moz-linear-gradient(#ddd, #fff); - background: -o-linear-gradient(#ddd, #fff); - background: -ms-linear-gradient(#ddd, #fff); - background: linear-gradient(#ddd, #fff); - -webkit-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; - -moz-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; - box-shadow: 0 0 8px rgba(0,0,0,.1) inset; -} -.toolbar ul li .activeButton { - background: #eee; - background: -webkit-linear-gradient(#ddd, #fff); - background: -moz-linear-gradient(#ddd, #fff); - background: -o-linear-gradient(#ddd, #fff); - background: -ms-linear-gradient(#ddd, #fff); - background: linear-gradient(#ddd, #fff); - -webkit-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; - -moz-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; - box-shadow: 0 0 8px rgba(0,0,0,.1) inset; -} -.toolbar ul li a { - background: #fff; - background: -webkit-linear-gradient(#fff, #f0f0f0); - background: -moz-linear-gradient(#fff, #f0f0f0); - background: -o-linear-gradient(#fff, #f0f0f0); - background: -ms-linear-gradient(#fff, #f0f0f0); - background: linear-gradient(#fff, #f0f0f0); - border: 1px solid #ccc; - border-radius: 3px; - color: #ccc; - cursor: pointer; - display: inline-block; - min-height: 18px; - overflow: hidden; - padding: 4px 5px; - text-align: center; - text-decoration: none; - min-width: 18px; + +.thin-scrollbar::-webkit-scrollbar-track { + background-color: #f6f6f6; + border: 1px solid #f0f0f0; } -.toolbar ul li a .buttonicon { - position: relative; - top: 1px; +.thin-scrollbar::-webkit-scrollbar { + width: 7px; } -.toolbar ul li a .buttontext { - color: #666; - font-size: 14px; - border:none; - background:none; - margin-top:1px; - color:#666; +.thin-scrollbar::-webkit-scrollbar-thumb { + background-color: #C5C5C5; } .buttontext::-moz-focus-inner { padding: 0; border: 0; } - .buttontext:focus{ /* Not sure why important is required here but it is */ border: 1px solid #666 !important; } - -.toolbar ul li a.grouped-left { - border-radius: 3px 0 0 3px; -} -.toolbar ul li a.grouped-middle { - border-radius: 0; - margin-left: -2px; - border-left: 0; -} -.toolbar ul li a.grouped-right { - border-radius: 0 3px 3px 0; - margin-left: -2px; - border-left: 0; -} -.toolbar ul li a.selected { - background: #eee !important; - background: -webkit-linear-gradient(#EEE, #F0F0F0) !important; - background: -moz-linear-gradient(#EEE, #F0F0F0) !important; - background: -o-linear-gradient(#EEE, #F0F0F0) !important; - background: -ms-linear-gradient(#EEE, #F0F0F0) !important; - background: linear-gradient(#EEE, #F0F0F0) !important; -} -.toolbar ul li select { - background: #fff; - padding: 4px; - line-height: 22px; /* fix for safari (win/mac) */ - height: 28px; /* fix for chrome (mac) */ - border-radius: 3px; - border: 1px solid #ccc; - outline: none; -} -.toolbar ul.menu_left { - left:0px; - right:250px; -} - -.toolbar ul.menu_right { - right:0px; -} - -li[data-key=showusers] > a { - min-width: 30px; - text-align: left; -} -li[data-key=showusers] > a #online_count { - color: #777; - font-size: 11px; - position: relative; - top: 2px; - padding-left: 2px; -} -#editbar{ - display:none; -} - -#editorcontainer { - position: absolute; - top: 37px; /* + 1px border */ - left: 0px; - right: 0px; - bottom: 0px; - z-index: 1; - - /* Required to be able to scroll on iOS: */ - -webkit-overflow-scrolling: touch; -} -#editorcontainer iframe { - height: 100%; - width: 100%; - padding: 0; - margin: 0; - left: 0; /* Required for safari fixes RTL */ -} -#editorloadingbox { - padding-top: 100px; - padding-bottom: 100px; - font-size: 2.5em; - color: #aaa; - text-align: center; - position: absolute; - width: 100%; - height: 30px; - z-index: 100; -} - -#editorloadingbox .passForm{ - padding:10px; -} - -#editorloadingbox input{ - padding:10px; -} - -#editorloadingbox button{ - padding:10px; -} - -.loadingAnimation{ - -webkit-animation: loadingAnimation 2s infinite linear; - animation: loadingAnimation 2s infinite linear; - font-family: "fontawesome-etherpad"; - font-size:24px; - z-index:150; - width:25px; - height:25px; -} - -.loadingAnimation:before{ - content: "\e80e"; -} - -@-webkit-keyframes loadingAnimation { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} -@keyframes loadingAnimation { - 0% { - -webkit-transform: rotate(0deg); - transform: rotate(0deg); - } - 100% { - -webkit-transform: rotate(359deg); - transform: rotate(359deg); - } -} - -#editorcontainerbox { - position: absolute; - bottom: 0; - top: 0; - width: 100%; -} -#padpage { - position: absolute; - top: 0px; - bottom: 0px; - width: 100%; -} -#padmain { - margin-top: 0px; - position: absolute; - top: 63px !important; - left: 0px; - right: 0px; - bottom: 0px; - zoom: 1; -} -#padeditor { - bottom: 0px; - left: 0; - position: absolute; - right: 0px; - top: 0; - zoom: 1; -} -#myswatchbox { - position: absolute; - left: 5px; - top: 5px; - width: 24px; - height: 24px; - border: 1px solid #000; - background: transparent; - cursor: pointer; -} -#myswatch { - width: 100%; - height: 100%; - background: transparent; /*...initially*/ -} -#mycolorpicker { - width: 232px; - height: 265px; - position: absolute; - left: -250px; - top: 0px; - z-index: 101; - display: none; - border-radius: 0 0 6px 6px; - background: #f7f7f7; - border: 1px solid #ccc; - border-top: 0; - padding-left: 10px; - padding-top: 10px; -} -#mycolorpickersave { - left: 10px; - font-weight: bold; -} -#mycolorpickercancel { - left: 85px -} -#mycolorpickersave, -#mycolorpickercancel { - background: #fff; - background: -webkit-linear-gradient(#fff, #ccc); - background: -moz-linear-gradient(#fff, #ccc); - background: -o-linear-gradient(#fff, #ccc); - background: -ms-linear-gradient(#fff, #ccc); - background: linear-gradient(#fff, #ccc); - border: 1px solid #ccc; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - font-size: 12px; - cursor: pointer; - color: #000; - overflow: hidden; - padding: 4px; - top: 240px; - text-align: center; - position: absolute; - width: 60px; -} -#mycolorpickerpreview { - position: absolute; - left: 207px; - top: 240px; - width: 16px; - height: 16px; - padding: 4px; - overflow: hidden; - color: #fff; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} -#myusernameform { - margin-left: 30px -} -#myusernameedit { - font-size: 1.3em; - color: #fff; - padding: 3px; - height: 18px; - margin: 0; - border: 0; - width: 122px; - background: transparent; -} -#myusernameform input.editable { - border: 1px solid #444 -} -#myuser .myusernameedithoverable:hover { - background: white; - color: black; -} -#mystatusform { - margin-left: 35px; - margin-top: 5px; -} -#mystatusedit { - font-size: 1.2em; - color: #777; - font-style: italic; - display: none; - padding: 2px; - height: 14px; - margin: 0; - border: 1px solid #bbb; - width: 199px; - background: transparent; -} -#myusernameform .editactive, -#myusernameform .editempty { - background: white; - border-left: 1px solid #c3c3c3; - border-top: 1px solid #c3c3c3; - border-right: 1px solid #e6e6e6; - border-bottom: 1px solid #e6e6e6; - color: #000; -} -#myusernameform .editempty { - color: #333 -} -#myswatchbox, #myusernameedit, #otheruserstable .swatch { - border: 1px solid #ccc !important; - color: #333; -} -table#otheruserstable { - display: none -} -#nootherusers { - padding: 10px; - font-size: 1.2em; - color: #eee; - font-weight: bold; -} -#nootherusers a { - color: #3C88FF -} -#otheruserstable td { - height: 26px; - vertical-align: middle; - padding: 0 2px; - color: #333; -} -#otheruserstable .swatch { - border: 1px solid #000; - width: 13px; - height: 13px; - overflow: hidden; - margin: 0 4px; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.usertdswatch { - width: 1% -} -.usertdname { - font-size: 1.3em; - color: #444; -} -.usertdstatus { - font-size: 1.1em; - font-style: italic; - color: #999; -} -.usertdactivity { - font-size: 1.1em; - color: #777; -} -.usertdname input { - border: 1px solid #bbb; - width: 80px; - padding: 2px; -} -.usertdname input.editactive, -.usertdname input.editempty { - background: white; - border-left: 1px solid #c3c3c3; - border-top: 1px solid #c3c3c3; - border-right: 1px solid #e6e6e6; - border-bottom: 1px solid #e6e6e6; -} -.usertdname input.editempty { - color: #888; - font-style: italic; -} - -#connectivity { - z-index: 600 !important; -} - -#connectivity * { - display: none; -} - -#connectivity .visible, -#connectivity .visible * { - display: block; -} - -/* styles for the automatic reconnection timer: */ -#connectivity .visible.with_reconnect_timer button, -#connectivity .visible.with_reconnect_timer .reconnecttimer * { - display: inline-block; -} - -#connectivity .with_reconnect_timer .hidden, -#connectivity .with_reconnect_timer #defaulttext.hidden, -#connectivity .with_reconnect_timer button.hidden { - display: none; -} - -#connectivity .with_reconnect_timer #cancelreconnect { - margin-left: 10px; -} -/* end of styles for the automatic reconnection timer */ - -#reconnect_form button { - font-size: 12pt; - padding: 5px; -} - -.toolbar #overlay { - z-index: 500; - display: none; - background-repeat: repeat-both; - width: 100%; - position: absolute; - height: inherit; - left: 0; - top: 0; -} -* html #overlay { - /* for IE 6+ */ - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)"; - filter: alpha(opacity=100); - opacity: 1; /* in case this is looked at */ - background-image: none; - background-repeat: no-repeat; /* scale the image */ -} - -#chatbox { - position: absolute; - bottom: 0px; - right: 20px; - width: 180px; - height: 200px; - z-index: 400; - background-color: #f7f7f7; - border-left: 1px solid #999; - border-right: 1px solid #999; - border-top: 1px solid #999; - padding: 3px; - padding-bottom: 10px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - display: none; -} -#chattext { - background-color: white; - border: 1px solid white; - -ms-overflow-y: scroll; - overflow-y: scroll; - font-size: 12px; - position: absolute; - right: 0px; - left: 0px; - top: 25px; - bottom: 25px; - z-index: 1002; -} -#chattext p { - padding: 3px; - -ms-overflow-x: hidden; - overflow-x: hidden; -} -.chatloadmessages -{ - margin-bottom: 5px; - margin-top: 5px; - margin-left: auto; - margin-right: auto; - display: block; -} -#chatloadmessagesbutton -{ - line-height: 1.8em; -} -#chatloadmessagesball -{ - display: none; -} -#chatinputbox { - padding: 3px 2px; - position: absolute; - bottom: 0px; - right: 0px; - left: 3px; -} -#chatlabel { - font-size: 13px; - font-weight: bold; - color: #555; - text-decoration: none; - margin-right: 3px; - vertical-align: middle; -} -#chatinput { - border: 1px solid #BBBBBB; - width: 100%; - float: right; -} -#chaticon { - z-index: 400; - position: fixed; - bottom: 0px; - right: 20px; - padding: 5px; - border-left: 1px solid #999; - border-right: 1px solid #999; - border-top: 1px solid #999; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - background-color: #fff; - cursor: pointer; - display: none; -} -#chaticon a { - text-decoration: none -} -#chatcounter { - color: #777; - font-size: 10px; - vertical-align: middle; -} -#titlebar { - line-height: 16px; - font-weight: bold; - color: #555; - position: relative; - bottom: 2px; -} -#titlelabel { - font-size: 13px; - margin: 4px 0 0 4px; - position: absolute; -} -#titlesticky{ - font-size: 10px; - padding-top:2px; - float: right; - text-align: right; - text-decoration: none; - cursor: pointer; - color: #555; -} -#titlecross { - font-size: 25px; - float: right; - text-align: right; - text-decoration: none; - cursor: pointer; - color: #555; -} -.time { - float: right; - color: #333; - font-style: italic; - font-size: 10px; - margin-left: 3px; - margin-right: 3px; - margin-top: 2px; -} -#exportColumn{ - margin-top:20px; -} -.exporttype { - margin-top: 4px; - background-repeat: no-repeat; - padding-left: 25px; - color: #333; - text-decoration: none; - padding-bottom:2px; - display:inline; - padding-left:5px; - font-family: "Arial"; -} -.exportlink{ - font-family: "fontawesome-etherpad"; - display:block; - margin:5px; - color:#666; -} -#exporthtmla:before { - content: "\e826"; -} -#exportplaina:before { - content: "\e802"; -} -#exportworda:before { - content: "\e804"; -} -#exportpdfa:before { - content: "\e803"; -} -#exportetherpada:before { - content: "\e806"; -} -#exportopena:before { - content: "\e805"; -} - -/* hidden element */ -#importstatusball, -#importmessagesuccess, -#importmessageabiword { - display: none; -} - -.throbbold{ - font-weight:bold; -} - -#importmessageabiword { - color: #900; - font-size: small; -} - -#importsubmitinput { - margin-top: 12px; - padding:2px 4px 2px 4px; -} -#chatthrob { - display: none; - position: absolute; - bottom: 40px; - font-size: 14px; - width: 150px; - height: 40px; - right: 20px; - z-index: 200; - background-color: #000; - color: white; - background-color: rgb(0,0,0); - background-color: rgba(0,0,0,0.7); - padding: 10px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)"; - filter: alpha(opacity=80); - opacity: .8; -} -.buttonicon { - width: 16px; - height: 16px; - display: inline-block; - vertical-align: middle; - border: none; - padding: 0; - background: none; - font-family: "fontawesome-etherpad"; - font-size: 15px; - font-style: normal; - font-weight: normal; - color: #666; - cursor: pointer; -} - -.buttonicon::-moz-focus-inner { - padding: 0; - border: 0 -} - -.buttonicon:before { - font-family: "fontawesome-etherpad"; -} - -.buttonicon:focus{ - border: 1px solid #666; -} -.buttonicon-bold:before { - content: "\e81c"; -} -.buttonicon-italic:before { - content: "\e81d"; -} -.buttonicon-underline:before { - content: "\e817"; -} -.buttonicon-strikethrough:before { - content: "\e818"; -} -.buttonicon-insertorderedlist:before { - content: "\e816"; -} -.buttonicon-insertunorderedlist:before { - content: "\e815"; -} -.buttonicon-indent:before { - content: "\e814"; -} -.buttonicon-outdent:before { - content: "\e813"; -} -.buttonicon-undo:before { - content: "\e823"; -} -.buttonicon-redo:before { - content: "\e824"; -} -.buttonicon-clearauthorship:before { - content: "\e80d"; -} -.buttonicon-settings:before { - content: "\e833"; -} -.buttonicon-import_export:before { - content: "\e834"; -} -.buttonicon-embed:before { - content: "\e827"; -} -.buttonicon-history:before { - content: "\e837"; -} -.buttonicon-chat:before { - content: "\e829"; -} -.buttonicon-showusers:before { - content: "\e808"; -} -.buttonicon-savedRevision:before { - content: "\e835"; -} -#focusprotector { - z-index: 100; - position: absolute; - bottom: 0px; - top: 0px; - left: 0px; - right: 0px; - background-color: white; - -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=1)"; - filter: alpha(opacity=1); - opacity: 0.01; - display: none; -} .rtl { direction: RTL } -#chattext p { - word-wrap: break-word -} + /* fix for misaligned checkboxes */ input[type=checkbox] { vertical-align: -1px } +input { + color: inherit; +} .right { float: right } -.popup { - font-size: 12px; - width: 80%; - max-width: 500px; - padding: 10px; - border-radius: 0 0 6px 6px; - border: 1px solid #ccc; - border-top: none; - background: #f7f7f7; - background: -webkit-linear-gradient(#F7F7F7, #EEE); - background: -moz-linear-gradient(#F7F7F7, #EEE); - background: -ms-linear-gradient(#F7F7F7, #EEE); - background: -o-linear-gradient(#F7F7F7, #EEE); - background: linear-gradient(#F7F7F7, #EEE); - -webkit-box-shadow: 0 0 8px #888; - -moz-box-shadow: 0 0 8px #888; - box-shadow: 0 2px 4px #ddd; - color: #222; -} -.popup input[type=text] { - width: 100%; - padding: 5px; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - display: block; - margin-top: 10px; -} -.popup input[type=text], #users input[type=text] { - outline: none; -} -.popup button { - padding: 5px; - font-size: 14px; -} -.popup a { - text-decoration: none -} -.popup h1 { - color: #555; - font-size: 18px -} -.popup h2 { - color: #777; - font-size: 15px -} -.popup p { - margin: 5px 0 -} -.popup select { - background: #fff; - padding: 2px; - height: 24px; - border-radius: 3px; - border: 1px solid #ccc; - outline: none; - width: 120px; -} -.row { - float: left; - width: 100%; -} -.row + .row { - margin-top: 15px; -} -.column { - float: left; - width:50%; -} -#settings, -#import_export, -#embed, -#connectivity, -#users { - position: absolute; - top: 38px; - right: 20px; - display: none; - z-index: 500; -} -.stickyChat { - background-color: #f1f1f1 !important; - right: 0px !important; - top: 37px; - -webkit-border-radius: 0px !important; - -moz-border-radius: 0px !important; - border-radius: 0px !important; - height: auto !important; - border: none !important; - border-left: 1px solid #ccc !important; - width: 185px !important; -} -.chatAndUsers{ - display:block !important; - right:0px !important; - border-radius:0px !important; - width:182px !important; -/* Below makes UI look weird when X makes editbar flow onto two lines */ -/* margin:2px 0 0 0 !important;*/ - border: none !important; - border-bottom: 1px solid #ccc !important; - height:155px !important; - border-left: 1px solid #ccc !important; -} -.chatAndUsers > #otherusers{ - max-height: 100px; - overflow-y: auto; -} -.chatAndUsersChat > div > #titlecross{ - display:none; -} -.chatAndUsersChat{ - bottom:0px !important; - padding:0 !important; - margin: 165px 0px 0px 0px; - right:0 !important; - width:182px !important; - border: none !important; - padding:5px !important; - border-left: 1px solid #ccc !important; -} -@media screen and (max-width: 600px) { - .toolbar ul li.separator { - display: none; - } - .toolbar ul li a { - padding: 4px 1px - } - .toolbar ul.menu_left { - left:0px; - right:150px; - } +@media (max-width: 800px) { + .hide-for-mobile { display: none; } } -@media all and (max-width: 400px){ - #gritter-notice-wrapper{ - max-height:172px; - overflow:hidden; - width:100% !important; - background-color: #ccc; - bottom:20px; - left:0px; - right:0px; - color:#000; - } - .gritter-close { - display:block !important; - left: auto !important; - right:5px; - } - #gritter-notice-wrapper.bottom-right{ - left:0px !important; - bottom:30px !important; - right:0px !important; - } - .gritter-item p{ - color:black; - font-size:16px; - } - .gritter-title{ - text-shadow: none !important; - color:black; - } - .gritter-item{ - padding:2px 11px 8px 4px; - } - .gritter-item-wrapper{ - margin:0; - } - .gritter-item-wrapper > div{ - background: none; - } - #editorcontainer { - top: 68px; - } - #editbar { - height: 62px; - } - .toolbar ul.menu_left { - left:0px; - right:100px; - } - .toolbar ul.menu_right { - right:0px; - } - .popup { - width:100%; - max-width:300px; - top: 72px !important; - } -} - -/* Mobile devices */ -@media only screen and (min-device-width: 320px) and (max-device-width: 720px) { - #users { - top: auto; - right:0px !important; - bottom: 33px; - border-radius: 0px !important; - height: 55px !important; - overflow: auto; - } - #mycolorpicker { - left: 0px; - top:37px !important; - position:fixed; - /* #mycolorpicker: width -#users: width */; - } - #editorcontainer { - margin-bottom: 33px - } - /* cancel non-mobile border (will be defined on ".toolbar ul.menu_left" bellow) */ - .toolbar { - border-bottom: 0; - } - .toolbar ul { - background: #f7f7f7; - background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -moz-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -o-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: linear-gradient(#f7f7f7, #f1f1f1 80%); - width: 100%; - overflow: hidden; - } - .toolbar ul.menu_left { - right:0px; - position: fixed; - top: 0; - padding-top: 4px; - border-bottom: 1px solid #ccc; - z-index: 10; - } - .toolbar ul.menu_right { - right:0px !important; - height: 32px; - position: fixed; - bottom: 0; - border-top: 1px solid #ccc; - } - .toolbar ul.menu_right > li:last-child { - float: right; - } - .toolbar ul.menu_right > li a { - border-radius: 0; - border: none; - background: none; - margin: 0; - padding: 8px; - } - .toolbar ul li a.selected { - background: none !important - } - li[data-key="showusers"] > a { - - margin-top:-10px; - padding-top:2px !important; - line-height:20px; - vertical-align:top !important; - } - #chaticon { - position:fixed; - right:48px; - } - .popup { - -webkit-border-radius: 0; - -moz-border-radius: 0; - border-radius: 0; - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - -ms-box-sizing: border-box; - box-sizing: border-box; - width: 100%; - } - #settings, - #import_export, - #connectivity, - #embed { - top:auto; - left: 0; - bottom: 33px; - right: 0; - } - .toolbar ul li .separator { - display: none - } - #online_count { - line-height: 24px - } - #chatbox{ - position:fixed; - bottom:33px !important; - margin: 65px 0 0 0; - } - #gritter-notice-wrapper{ - bottom:43px !important; - right:10px !important; - } -} - -#passwordRequired{ - display:none; -} - -#permissionDenied{ - display:none; -} - -#wrongPassword{ - display:none; -} - -#noCookie{ - display:none; -} - -/* gritter stuff */ -#gritter-notice-wrapper { - position:fixed; - top:20px; - right:20px; - width:301px; - z-index:9999; - background-color:#666; -} -#gritter-notice-wrapper.bottom-right { - top: auto; - left: auto; - bottom: 20px; - right: 20px; -} -.gritter-item-wrapper { - position:relative; - margin:0 0 10px 0; -} - -.gritter-top { - height:10px; -} -.hover .gritter-top { - background-position:right -30px; -} -.gritter-bottom { - height:8px; - margin:0; -} -.hover .gritter-bottom { - background-position: bottom right; -} -.gritter-item { - display:block; - color:#eee; - padding:2px 11px 8px 11px; - font-size: 11px; - font-family:verdana; -} -.hover .gritter-item { - background-position:right -40px; -} -.gritter-item p { - padding:0; - margin:0; -} -.gritter-close { - display:none; - position:absolute; - top:5px; - left:3px; - cursor:pointer; - width:30px; - height:30px; -} -.gritter-title { - font-size:14px; - font-weight:bold; - padding:0 0 7px 0; - display:block; - text-shadow:1px 1px 0 #000; /* Not supported by IE :( */ -} -.gritter-image { - width:48px; - height:48px; - float:left; -} -.gritter-with-image, -.gritter-without-image { - padding:0 0 5px 0; -} -.gritter-with-image { - width:220px; - float:right; -} -/* for the light (white) version of the gritter notice */ -.gritter-light .gritter-item, -.gritter-light .gritter-bottom, -.gritter-light .gritter-top, -.gritter-close { - color: #222; -} -.gritter-light .gritter-title { - text-shadow: none; -} -/* End of gritter stuff */ - -/* Montserrat Font */ -@font-face { - font-family: "Montserrat"; - src: url("../../static/font/Montserrat-Light.otf") format("opentype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "Montserrat"; - src: url("../../static/font/Montserrat-Regular.otf") format("opentype"); - font-weight: bold; - font-style: normal; -} -/* End of Monterrat Font */ - -@font-face { - font-family: opendyslexic; - src: url("../../static/font/opendyslexic.otf") format("opentype"); -} - -/* Roboto Mono */ -@font-face { - font-family: "RobotoMono"; - src: url("../../static/font/RobotoMono-Regular.ttf") format("truetype"); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: "RobotoMono"; - src: url("../../static/font/RobotoMono-Bold.ttf") format("truetype"); - font-weight: bold; - font-style: normal; -} -/* End of Roboto Mono */ - -@font-face { - font-family: "fontawesome-etherpad"; - src:url("../../static/font/fontawesome-etherpad.eot"); - src:url("../../static/font/fontawesome-etherpad.eot?#iefix") format("embedded-opentype"), - url("../../static/font/fontawesome-etherpad.woff") format("woff"), - url("../../static/font/fontawesome-etherpad.ttf") format("truetype"), - url("../../static/font/fontawesome-etherpad.svg#fontawesome-etherpad") format("svg"); - font-weight: normal; - font-style: normal; - -} - -[data-icon]:before, -[class^="icon-"]:before, -[class*=" icon-"]:before { - font-family: "fontawesome-etherpad" !important; - font-style: normal !important; - font-weight: normal !important; - font-variant: normal !important; - text-transform: none !important; - speak: none; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -.hideControlsEditor{ - top:0px !important; -} -.hideControlsEditbar{ - display:none !important; +#importmessagepermission { + display: none; } diff --git a/src/static/css/pad/chat.css b/src/static/css/pad/chat.css new file mode 100644 index 00000000000..39df3ce3097 --- /dev/null +++ b/src/static/css/pad/chat.css @@ -0,0 +1,164 @@ +#chaticon, #chatbox { + visibility: hidden; + z-index: 400; + position: absolute; + bottom: 0px; + right: 25px; +} +#chaticon.visible, #chatbox.visible { + visibility: visible; +} +#chaticon { + border-top-left-radius: 5px; + border-top-right-radius: 5px; + border: 1px solid #ccc; + border-bottom: none; +} +.chat-content { + width: 400px; + height: 300px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + display: flex; + border: 1px solid #ccc; + border-bottom: none; + z-index: 401; + background-color: #f7f7f7; + flex-direction: column; + transition: all 0.3s cubic-bezier(0.74, -0.05, 0.27, 1.75); + opacity: .3; + transform: scale(.5); + transform-origin: 100% 100% +} +#chatbox.visible .chat-content{ + opacity: 1; + transform: scale(1); +} + +#chatbox.stickyChat { + position: relative; + width: auto; + flex: 1 auto; /* take reminaning vertical space */ + height: 100%; + right: 0; + display: flex; +} +#chatbox.stickyChat .chat-content { + background-color: #f1f1f1; + border-radius: 0; + border: none; + border-left: 1px solid #ccc; + height: 100%; + width: 100%; +} +#chatbox.stickyChat .chat-content .stick-to-screen-btn { + display: none; +} +#chatbox.stickyChat.chatAndUsersChat .chat-content .hide-reduce-btn { + display:none; +} + +/* -- TITLE BAR -- */ +#titlebar { + font-weight: bold; + padding: 5px; +} +#titlebar #titlelabel { + margin: 4px 0 0 4px; + display: inline; + font-size: 1.4rem; +} +#titlebar .stick-to-screen-btn, +#titlebar .hide-reduce-btn { + font-size: 25px; + color: inherit; + float: right; + text-align: right; + text-decoration: none; + cursor: pointer; +} +#titlebar .stick-to-screen-btn { + font-size: 10px; + padding-top: 2px; +} + +/* -- MESSAGES -- */ +#chattext { + background-color: white; + overflow-y: auto; + flex: 1 auto; + height: 0; /* strange bug on firefox, if height is not set, the chattext grow bigger than the maximum height */ +} +#chattext p { + padding: 3px; + overflow-x: hidden; + word-wrap: break-word; +} +#chattext .time { + float: right; + font-style: italic; + font-size: .85rem; + opacity: .8; + margin-left: 3px; + margin-right: 2px; +} + +/* -- INPUT BOX -- */ +#chatinputbox { + padding: 5px; +} +#chatinputbox #chatinput { + width: 100%; +} + + +/* -- CHAT ICON -- */ +#chaticon { + background-color: #fff; + cursor: pointer; + display: none; + padding: 5px; +} +#chaticon a { + text-decoration: none +} +#chaticon #chatlabel { + font-weight: bold; + text-decoration: none; + margin-right: 3px; + vertical-align: middle; +} +#chaticon #chatcounter { + font-size: .8rem; + vertical-align: middle; + margin-left: 5px; +} + +/* -- LOAD MESSAGES -- */ +.chatloadmessages +{ + margin-bottom: 5px; + margin-top: 5px; + margin-left: auto; + margin-right: auto; + display: block; +} +#chatloadmessagesbutton +{ + line-height: 1.8em; +} +#chatloadmessagesball +{ + display: none; +} + +@media only screen and (max-width: 720px) { + #chatbox { + right: 0; + bottom: 0; + left: 0; + } + #chatbox .chat-content { + width: 100%; + } +} diff --git a/src/static/css/pad/fonts.css b/src/static/css/pad/fonts.css new file mode 100644 index 00000000000..60b083ff6b4 --- /dev/null +++ b/src/static/css/pad/fonts.css @@ -0,0 +1,61 @@ +/* Montserrat Font */ +@font-face { + font-family: "Montserrat"; + src: url("../../../static/font/Montserrat-Light.otf") format("opentype"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "Montserrat"; + src: url("../../../static/font/Montserrat-Regular.otf") format("opentype"); + font-weight: bold; + font-style: normal; +} +/* End of Monterrat Font */ + +@font-face { + font-family: opendyslexic; + src: url("../../../static/font/opendyslexic.otf") format("opentype"); +} +@font-face { + font-family: "RobotoMono"; + src: url("../../../static/font/RobotoMono-Regular.ttf") format("truetype"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "RobotoMono"; + src: url("../../../static/font/RobotoMono-Bold.ttf") format("truetype"); + font-weight: bold; + font-style: normal; +} +@font-face { + font-family: "Quicksand"; + src: url("../../../static/font/Quicksand-Regular.ttf") format("truetype"); + font-weight: 300; + font-style: normal; +} +@font-face { + font-family: "Quicksand"; + src: url("../../../static/font/Quicksand-Medium.ttf") format("truetype"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "Quicksand"; + src: url("../../../static/font/Quicksand-Bold.ttf") format("truetype"); + font-weight: bold; + font-style: normal; +} +@font-face { + font-family: "Roboto"; + src: url("../../../static/font/Roboto-Regular.ttf") format("truetype"); + font-weight: normal; + font-style: normal; +} +@font-face { + font-family: "Roboto"; + src: url("../../../static/font/Roboto-Bold.ttf") format("truetype"); + font-weight: bold; + font-style: normal; +} \ No newline at end of file diff --git a/src/static/css/pad/form.css b/src/static/css/pad/form.css new file mode 100644 index 00000000000..d0dcb759680 --- /dev/null +++ b/src/static/css/pad/form.css @@ -0,0 +1,177 @@ +select, .nice-select { + -webkit-tap-highlight-color: transparent; + background-color: #fff; + border-radius: 3px; + border: 1px solid #ccc; + box-sizing: border-box; + clear: both; + cursor: pointer; + display: inline-block; + font-family: inherit; + font-weight: normal; + height: 28px; + line-height: 28px; + outline: none; + padding-left: 8px; + padding-right: 24px; + position: relative; + text-align: left !important; + -webkit-transition: all 0.2s ease-in-out; + transition: all 0.2s ease-in-out; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + white-space: nowrap; + width: 120px; + text-transform: capitalize; +} +.popup .nice-select { + padding: 4px 24px 4px 8px; +} +.nice-select:hover { + border-color: #dbdbdb; +} +.nice-select:active,.nice-select.open,.nice-select:focus { + /*border-color: #999;*/ +} +.nice-select:after { + border-bottom: 2px solid #999; + border-right: 2px solid #999; + content: ''; + display: block; + height: 5px; + margin-top: -3px; + pointer-events: none; + position: absolute; + right: 10px; + top: 50%; + -webkit-transform-origin: 66% 66%; + -ms-transform-origin: 66% 66%; + transform-origin: 66% 66%; + -webkit-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + -webkit-transition: all 0.15s ease-in-out; + transition: all 0.15s ease-in-out; + width: 5px; +} +.nice-select.open:after { + -webkit-transform: rotate(-135deg); + -ms-transform: rotate(-135deg); + transform: rotate(-135deg); +} +.nice-select.open .list { + opacity: 1; + pointer-events: auto; + -webkit-transform: scale(1) translateY(0); + -ms-transform: scale(1) translateY(0); + transform: scale(1) translateY(0); +} +.nice-select.disabled { + border-color: #ededed; + color: #999; + pointer-events: none; +} +.nice-select.disabled:after { + border-color: #cccccc; +} +.nice-select.wide { + width: 100%; +} +.nice-select.wide .list { + left: 0 !important; + right: 0 !important; +} +.nice-select.right { + float: right; +} +.nice-select.right .list { + left: auto; + right: 0; +} +.nice-select.small { + font-size: 12px; + height: 36px; + line-height: 34px; +} +.nice-select.small:after { + height: 4px; + width: 4px; +} +.nice-select.small .option { + line-height: 34px; + min-height: 34px; +} +.nice-select .list { + display: block; + background-color: #fff; + border-radius: 3px; + box-shadow: 0 0 0 1px rgba(68, 68, 68, 0.11); + box-sizing: border-box; + margin-top: 4px; + opacity: 0; + overflow: auto; + padding: 0; + pointer-events: none; + position: absolute; + top: 100%; + left: 0; + max-height: 10px; + -webkit-transform-origin: 50% 0; + -ms-transform-origin: 50% 0; + transform-origin: 50% 0; + -webkit-transform: scale(0.75) translateY(-21px); + -ms-transform: scale(0.75) translateY(-21px); + transform: scale(0.75) translateY(-21px); + -webkit-transition: all 0.2s cubic-bezier(0.5, 0, 0, 1.25), opacity 0.15s ease-out; + transition: all 0.2s cubic-bezier(0.5, 0, 0.08, 1.10), opacity 0.15s ease-out; + z-index: 9; +} +.nice-select.reverse .list { + bottom: calc(100% + 5px); + top: auto; +} +.toolbar .nice-select .list { + position: fixed; + top: auto; + left: auto; +} +.nice-select .list:hover .option:not(:hover) { + background-color: transparent !important; +} +.nice-select .option { + cursor: pointer; + font-weight: 400; + line-height: 35px; + list-style: none; + min-height: 35px; + outline: none; + margin: 0; + padding-left: 8px; + padding-right: 8px; + text-align: left; + -webkit-transition: all 0.2s; + transition: all 0.2s; + text-transform: capitalize; +} +.nice-select .option:hover,.nice-select .option.focus,.nice-select .option.selected.focus { + background-color: #f6f6f6; +} +.nice-select .option[data-value="dummy"] { + display: none; +} +.nice-select .option.selected { + font-weight: bold; +} +.nice-select .option.disabled { + background-color: transparent; + color: #999; + cursor: default; +} + .no-csspointerevents.nice-select .list { + display: none; +} + .no-csspointerevents.nice-select.open .list { + display: block; +} diff --git a/src/static/css/pad/gritter.css b/src/static/css/pad/gritter.css new file mode 100644 index 00000000000..20d70be46b5 --- /dev/null +++ b/src/static/css/pad/gritter.css @@ -0,0 +1,49 @@ +#gritter-container { + position: absolute; + right: 50%; + transform: translateX(50%); + text-align: center; + z-index: 9999; +} +#gritter-container.top { + top: 20px; +} +#gritter-container.bottom { + bottom: 20px; +} + +.gritter-item.popup { + position: relative; + max-width: 450px; + visibility: visible; + right: auto !important; + left: auto !important; + top: auto; + bottom: auto; +} + +.gritter-item .popup-content { + display: flex; +} + +.gritter-item .gritter-content { + flex: 1 auto; + text-align: center; +} + +.gritter-item .gritter-close { + align-self: center; +} + +.gritter-item.error .popup-content { + color: #a84341; + background-color: #eed3d4; +} + +@media (max-width: 720px) { + #gritter-container { + left: 1rem; + right: 1rem; + transform: none; + } +} \ No newline at end of file diff --git a/src/static/css/pad/icons.css b/src/static/css/pad/icons.css new file mode 100644 index 00000000000..ab0f45b322e --- /dev/null +++ b/src/static/css/pad/icons.css @@ -0,0 +1,192 @@ +@font-face { + font-family: "fontawesome-etherpad"; + src:url("../../../static/font/fontawesome-etherpad.eot?2"); + src:url("../../../static/font/fontawesome-etherpad.eot?2#iefix") format("embedded-opentype"), + url("../../../static/font/fontawesome-etherpad.woff?2") format("woff"), + url("../../../static/font/fontawesome-etherpad.ttf?2") format("truetype"), + url("../../../static/font/fontawesome-etherpad.svg#fontawesome-etherpad") format("svg"); + font-weight: normal; + font-style: normal; + +} + +.buttonicon { + border: none; + padding: 0; + background: none; + text-align: center; + font-style: normal; + font-weight: normal; + position: relative; + cursor: pointer; + -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + font-style: normal; + font-variant: normal; + text-rendering: auto; +} + +.buttonicon:before, [class^="buttonicon-"]:before, [class*=" buttonicon-"]:before { + font-family: "fontawesome-etherpad"; + font-style: normal; + font-weight: normal; + speak: none; + font-size: 15px; + display: inline-block; + text-decoration: inherit; + width: 1em; + margin: 0; + text-align: center; + + /* For safety - reset parent styles, that can break glyph codes*/ + font-variant: normal; + text-transform: none; + + /* Font smoothing. That was taken from TWBS */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.buttonicon-insertorderedlist:before { + content: "\e844"; +} +.buttonicon-insertunorderedlist:before { + content: "\e82a"; +} +.buttonicon-clearauthorship:before { + content: "\e843"; + left: -9px; + position: absolute; + top: -9px; +} +.buttonicon-settings:before { + content: "\e851"; +} +.buttonicon-import_export:before { + content: "\e837"; +} +.buttonicon-embed:before { + content: "\e853"; +} +.buttonicon-history:before { + content: "\e837"; +} +.buttonicon-chat:before { + content: "\e82d"; +} +.buttonicon-showusers:before { + content: "\e835"; +} +.buttonicon-savedRevision:before { + content: "\e856"; +} +.buttonicon-undo:before { content: '\e84b'; } /* '' */ +.buttonicon-redo:before { content: '\e84c'; } /* '' */ + +.ep_font_size > a > .buttonicon:before { content: '\e852' !important; } +.ep_font_color .buttonicon:before { content: '\e84e' !important; border-bottom: solid 2px #e42a2a; } + +.buttonicon-underline:before { + top: -8px; + left: -8px; + position: absolute; +} + +/* COPY CSS GENERATED BY FONTELLO HERE */ +.buttonicon-sync-alt:before { content: '\e800'; } /* '' */ +.buttonicon-print:before { content: '\e801'; } /* '' */ +.buttonicon-stop:before { content: '\e802'; } /* '' */ +.buttonicon-play:before { content: '\e803'; } /* '' */ +.buttonicon-align-center:before { content: '\e804'; } /* '' */ +.buttonicon-align-justify:before { content: '\e805'; } /* '' */ +.buttonicon-align-left:before { content: '\e806'; } /* '' */ +.buttonicon-align-right:before { content: '\e807'; } /* '' */ +.buttonicon-pencil-alt:before { content: '\e808'; } /* '' */ +.buttonicon-file-code:before { content: '\e809'; } /* '' */ +.buttonicon-mail:before { content: '\e80a'; } /* '' */ +.buttonicon-trash:before { content: '\e80e'; } /* '' */ +.buttonicon-times:before { content: '\e826'; } /* '' */ +.buttonicon-pause:before { content: '\e829'; } /* '' */ +.buttonicon-list-ul:before { content: '\e82a'; } /* '' */ +.buttonicon-step-backward:before { content: '\e82b'; } /* '' */ +.buttonicon-step-forward:before { content: '\e82c'; } /* '' */ +.buttonicon-comments:before { content: '\e82d'; } /* '' */ +.buttonicon-heading:before { content: '\e82e'; } /* '' */ +.buttonicon-brush:before { content: '\e830'; } /* '' */ +.buttonicon-slideshare:before { content: '\e831'; } /* '' */ +.buttonicon-tasks:before { content: '\e832'; } /* '' */ +.buttonicon-superscript:before { content: '\e833'; } /* '' */ +.buttonicon-subscript:before { content: '\e834'; } /* '' */ +.buttonicon-users:before { content: '\e835'; } /* '' */ +.buttonicon-gauge:before { content: '\e836'; } /* '' */ +.buttonicon-exchange-alt:before { content: '\e837'; } /* '' */ +.buttonicon-text-width:before { content: '\e838'; } /* '' */ +.buttonicon-pencil:before { content: '\e839'; } /* '' */ +.buttonicon-picture:before { content: '\e83a'; } /* '' */ +.buttonicon-video:before { content: '\e83b'; } /* '' */ +.buttonicon-video-slash:before { content: '\e83c'; } /* '' */ +.buttonicon-microphone-alt:before { content: '\e83d'; } /* '' */ +.buttonicon-microphone-alt-slash:before { content: '\e83e'; } /* '' */ +.buttonicon-compress:before { content: '\e83f'; } /* '' */ +.buttonicon-expand:before { content: '\e840'; } /* '' */ +.buttonicon-spin5:before { content: '\e841'; } /* '' */ +.buttonicon-eye-slash:before { content: '\e843'; } /* '' */ +.buttonicon-list-ol:before { content: '\e844'; } /* '' */ +.buttonicon-bold:before { content: '\e845'; } /* '' */ +.buttonicon-underline:before { content: '\e846'; } /* '' */ +.buttonicon-italic:before { content: '\e847'; } /* '' */ +.buttonicon-strikethrough:before { content: '\e848'; } /* '' */ +.buttonicon-indent:before { content: '\e849'; } /* '' */ +.buttonicon-outdent:before { content: '\e84a'; } /* '' */ +.buttonicon-undo-alt:before { content: '\e84b'; } /* '' */ +.buttonicon-redo-alt:before { content: '\e84c'; } /* '' */ +.buttonicon-link:before { content: '\e84d'; } /* '' */ +.buttonicon-font:before { content: '\e84e'; } /* '' */ +.buttonicon-comment-medical:before { content: '\e84f'; } /* '' */ +.buttonicon-comment:before { content: '\e850'; } /* '' */ +.buttonicon-cog:before { content: '\e851'; } /* '' */ +.buttonicon-text-height:before { content: '\e852'; } /* '' */ +.buttonicon-share-alt:before { content: '\e853'; } /* '' */ +.buttonicon-code:before { content: '\e854'; } /* '' */ +.buttonicon-history:before { content: '\e855'; } /* '' */ +.buttonicon-star:before { content: '\e856'; } /* '' */ +.buttonicon-file-import:before { content: '\e857'; } /* '' */ +.buttonicon-file-download:before { content: '\e858'; } /* '' */ +.buttonicon-file-pdf:before { content: '\e859'; } /* '' */ +.buttonicon-file-word:before { content: '\e85a'; } /* '' */ +.buttonicon-file-alt:before { content: '\e85b'; } /* '' */ +.buttonicon-file:before { content: '\e85c'; } /* '' */ +.buttonicon-file-powerpoint:before { content: '\e85d'; } /* '' */ +.buttonicon-table:before { content: '\f0ce'; } /* '' */ +/* END Of FONTELLO GENERATED CSS */ + +.icon-spin:before { + -webkit-animation: spinAnimation 2s infinite linear; + animation: spinAnimation 2s infinite linear; + font-family: "fontawesome-etherpad"; + font-size: 22px; + z-index: 150; + width: 22px; + height: 22px; +} + +@-webkit-keyframes spinAnimation { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes spinAnimation { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} \ No newline at end of file diff --git a/src/static/css/pad/layout.css b/src/static/css/pad/layout.css new file mode 100644 index 00000000000..0d583f32956 --- /dev/null +++ b/src/static/css/pad/layout.css @@ -0,0 +1,51 @@ +html, body { + width: 100%; + height: 100%; + margin: 0; + padding: 0; +} +html:not(.inner-editor), html:not(.inner-editor) body { + overflow: hidden; +} +body { + display: flex; + flex-direction: column; +} +#editbar { + height: auto; +} +#editorcontainerbox { + flex: 1 auto; + position: relative; /* for nested popup to use absolute positionning */ + background-color: #eee; + + /* For sticky chat */ + display: flex; + flex-direction: row; + height: 0; /* strange bug some browser need this to be working ok */ +} +#editorcontainerbox #editorcontainer { + display: flex; /* transfer flex properties to nested elements, here the iframe */ + height: auto; + flex: 1 auto; +} +#editorcontainerbox #editorcontainer iframe { + width: 100%; + height: auto; +} +#editorcontainerbox .sticky-container { /* container for #users, #chat, #toc (table of content) and so on... */ + display: flex; + flex-direction: column; + width: 200px; + max-width: 40%; + flex-shrink: 0; +} +#editorcontainerbox .sticky-container:not(.stikyUsers):not(.stickyChat) { + width: 0; /* hide when the container is empty */ +} + +@media only screen and (max-width: 720px) { + #editorcontainerbox { + margin-bottom: 39px; /* Leave space for the bottom toolbar on mobile */ + } +} diff --git a/src/static/css/pad/loadingbox.css b/src/static/css/pad/loadingbox.css new file mode 100644 index 00000000000..5e990cd7255 --- /dev/null +++ b/src/static/css/pad/loadingbox.css @@ -0,0 +1,27 @@ +#editorloadingbox { + padding-top: 100px; + padding-bottom: 100px; + font-size: 2.5em; + color: #aaa; + text-align: center; + position: absolute; + width: 100%; + height: 30px; + z-index: 100; +} + +#editorloadingbox .passForm{ + padding:10px; +} + +#editorloadingbox input{ + padding:10px; +} + +#editorloadingbox button{ + padding:10px; +} + +#passwordRequired, #permissionDenied, #wrongPassword, #noCookie { + display:none; +} \ No newline at end of file diff --git a/src/static/css/pad/normalize.css b/src/static/css/pad/normalize.css new file mode 100644 index 00000000000..cd04393347d --- /dev/null +++ b/src/static/css/pad/normalize.css @@ -0,0 +1,428 @@ +/*! normalize.css v3.0.2 | MIT License | git.io/normalize */ + +/** + * 1. Set default font family to sans-serif. + * 2. Prevent iOS text size adjust after orientation change, without disabling + * user zoom. + */ + +html { + font-family: sans-serif; /* 1 */ + -ms-text-size-adjust: 100%; /* 2 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +html { + box-sizing: border-box; +} +*, *:before, *:after { + box-sizing: border-box; +} +* { + margin: 0; + padding: 0; +} + +/** + * Remove default margin. + */ + +body { + margin: 0; +} + +/* HTML5 display definitions + ========================================================================== */ + +/** + * Correct `block` display not defined for any HTML5 element in IE 8/9. + * Correct `block` display not defined for `details` or `summary` in IE 10/11 + * and Firefox. + * Correct `block` display not defined for `main` in IE 11. + */ + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +main, +menu, +nav, +section, +summary { + display: block; +} + +/** + * 1. Correct `inline-block` display not defined in IE 8/9. + * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. + */ + +audio, +canvas, +progress, +video { + display: inline-block; /* 1 */ + vertical-align: baseline; /* 2 */ +} + +/** + * Prevent modern browsers from displaying `audio` without controls. + * Remove excess height in iOS 5 devices. + */ + +audio:not([controls]) { + display: none; + height: 0; +} + +/** + * Address `[hidden]` styling not present in IE 8/9/10. + * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. + */ + +[hidden], +template { + display: none; +} + +/* Links + ========================================================================== */ + +/** + * Remove the gray background color from active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * Improve readability when focused and also mouse hovered in all browsers. + */ + +a:active, +a:hover { + outline: 0; +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Address styling not present in IE 8/9/10/11, Safari, and Chrome. + */ + +abbr[title] { + border-bottom: 1px dotted; +} + +/** + * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. + */ + +b, +strong { + font-weight: bold; +} + +/** + * Address styling not present in Safari and Chrome. + */ + +dfn { + font-style: italic; +} + +/** + * Address styling not present in IE 8/9. + */ + +mark { + background: #ff0; + color: #000; +} + +/** + * Address inconsistent and variable font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` affecting `line-height` in all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sup { + top: -0.5em; +} + +sub { + bottom: -0.25em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove border when inside `a` element in IE 8/9/10. + */ + +img { + border: 0; +} + +/** + * Correct overflow not hidden in IE 9/10/11. + */ + +svg:not(:root) { + overflow: hidden; +} + +/* Grouping content + ========================================================================== */ + +/** + * Address margin not present in IE 8/9 and Safari. + */ + +figure { + margin: 1em 40px; +} + +/** + * Address differences between Firefox and other browsers. + */ + +hr { + -moz-box-sizing: content-box; + box-sizing: content-box; + height: 0; +} + +/** + * Contain overflow in all browsers. + */ + +pre { + overflow: auto; +} + +/** + * Address odd `em`-unit font size rendering in all browsers. + */ + +code, +kbd, +pre, +samp { + font-family: monospace, monospace; + font-size: 1em; +} + +/* Forms + ========================================================================== */ + +/** + * Known limitation: by default, Chrome and Safari on OS X allow very limited + * styling of `select`, unless a `border` property is set. + */ + +/** + * 1. Correct color not being inherited. + * Known issue: affects color of disabled elements. + * 2. Correct font properties not being inherited. + * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. + */ + +button, +input, +optgroup, +select, +textarea { + color: inherit; /* 1 */ + font: inherit; /* 2 */ + margin: 0; /* 3 */ +} + +/** + * Address `overflow` set to `hidden` in IE 8/9/10/11. + */ + +button { + overflow: visible; +} + +/** + * Address inconsistent `text-transform` inheritance for `button` and `select`. + * All other form control elements do not inherit `text-transform` values. + * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. + * Correct `select` style inheritance in Firefox. + */ + +button, +select { + text-transform: none; +} + +/** + * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` + * and `video` controls. + * 2. Correct inability to style clickable `input` types in iOS. + * 3. Improve usability and consistency of cursor style between image-type + * `input` and others. + */ + +/* 1 */ html input[type="button"], +button, +input[type="reset"], +input[type="submit"] { + -webkit-appearance: button; /* 2 */ + cursor: pointer; /* 3 */ +} + +/** + * Re-set default cursor for disabled elements. + */ + +button[disabled], +html input[disabled] { + cursor: default; +} + +/** + * Remove inner padding and border in Firefox 4+. + */ + +button::-moz-focus-inner, +input::-moz-focus-inner { + border: 0; + padding: 0; +} + +/** + * Address Firefox 4+ setting `line-height` on `input` using `!important` in + * the UA stylesheet. + */ + +input { + line-height: normal; +} + +/** + * It's recommended that you don't attempt to style these elements. + * Firefox's implementation doesn't respect box-sizing, padding, or width. + * + * 1. Address box sizing set to `content-box` in IE 8/9/10. + * 2. Remove excess padding in IE 8/9/10. + */ + +input[type="checkbox"], +input[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Fix the cursor style for Chrome's increment/decrement buttons. For certain + * `font-size` values of the `input`, it causes the cursor style of the + * decrement button to change from `default` to `text`. + */ + +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Address `appearance` set to `searchfield` in Safari and Chrome. + * 2. Address `box-sizing` set to `border-box` in Safari and Chrome + * (include `-moz` to future-proof). + */ + +input[type="search"] { + -webkit-appearance: textfield; /* 1 */ + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; /* 2 */ + box-sizing: content-box; +} + +/** + * Remove inner padding and search cancel button in Safari and Chrome on OS X. + * Safari (but not Chrome) clips the cancel button when the search input has + * padding (and `textfield` appearance). + */ + +input[type="search"]::-webkit-search-cancel-button, +input[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * Define consistent border, margin, and padding. + */ + +fieldset { + border: 1px solid #c0c0c0; + margin: 0 2px; + padding: 0.35em 0.625em 0.75em; +} + +/** + * 1. Correct `color` not being inherited in IE 8/9/10/11. + * 2. Remove padding so people aren't caught out if they zero out fieldsets. + */ + +legend { + border: 0; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Remove default vertical scrollbar in IE 8/9/10/11. + */ + +textarea { + overflow: auto; +} + +/** + * Don't inherit the `font-weight` (applied by a rule above). + * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. + */ + +optgroup { + font-weight: bold; +} + +/* Tables + ========================================================================== */ + +/** + * Remove most spacing between table cells. + */ + +table { + border-collapse: collapse; + border-spacing: 0; +} + +td, +th { + padding: 0; +} diff --git a/src/static/css/pad/popup.css b/src/static/css/pad/popup.css new file mode 100644 index 00000000000..fd4312cd23e --- /dev/null +++ b/src/static/css/pad/popup.css @@ -0,0 +1,86 @@ +.popup.popup-show, .popup#users.chatAndUsers { + visibility: visible; +} + +.popup > .popup-content { + transform: scale(0.7); + opacity: 0; + transition: all 0.3s cubic-bezier(0.74, -0.05, 0.27, 1.75) +} + +.popup.popup-show > .popup-content, .popup#users.chatAndUsers > .popup-content { + transform: scale(1); + opacity: 1; +} + +.popup { + position: absolute; + top: 10px; + right: 30px; + visibility: hidden; + z-index: 500; +} +#mycolorpicker { + top: 0; +} +.popup.toolbar-popup { + right: auto; + margin-left: -10px; +} +.popup-content { + padding: 10px; + border-radius: 6px; + border: 1px solid #ccc; + box-shadow: 0 2px 4px #ddd; + background: #f7f7f7; + min-width: 300px; + max-width: 600px; +} +.popup input[type=text] { + width: 100%; + padding: 5px; + display: block; + margin-top: 10px; +} +.popup input[type=text], #users input[type=text] { + outline: none; +} +.popup a { + text-decoration: none +} +.popup h1 { + font-size: 1.8rem; + margin-bottom: 10px; +} +.popup h2 { + opacity: .7; + margin: 10px 0; + font-size: 1.2rem; +} +.popup:not(.comment-modal) p { + margin: 5px 0; +} + +/* Mobile devices */ +@media only screen and (max-width: 720px) { + .popup { + border-radius: 0; + top: 1rem; + margin: 0 !important; + right: 1rem !important; + left: 1rem !important; + max-width: none !important; + } + .popup-content { + max-height: 80vh; + overflow: auto; + } + .popup#users .popup-content { + overflow: visible; + } + /* Move popup to the bottom, except popup linked to left toolbar, like hyperklink popup */ + .popup:not(.toolbar-popup) { + top: auto; + bottom: 1rem; + } +} \ No newline at end of file diff --git a/src/static/css/pad/popup_connectivity.css b/src/static/css/pad/popup_connectivity.css new file mode 100644 index 00000000000..80923341388 --- /dev/null +++ b/src/static/css/pad/popup_connectivity.css @@ -0,0 +1,24 @@ +#connectivity .popup-content * { + display: none; +} + +#connectivity .visible, +#connectivity .visible * { + display: block; +} + +/* styles for the automatic reconnection timer: */ +#connectivity .visible.with_reconnect_timer button, +#connectivity .visible.with_reconnect_timer .reconnecttimer * { + display: inline-block; +} + +#connectivity .with_reconnect_timer .hidden, +#connectivity .with_reconnect_timer #defaulttext.hidden, +#connectivity .with_reconnect_timer button.hidden { + display: none; +} + +#connectivity .with_reconnect_timer #cancelreconnect { + margin-left: 10px; +} \ No newline at end of file diff --git a/src/static/css/pad/popup_import_export.css b/src/static/css/pad/popup_import_export.css new file mode 100644 index 00000000000..3bfe0722e75 --- /dev/null +++ b/src/static/css/pad/popup_import_export.css @@ -0,0 +1,26 @@ +.readonly .acl-write { + display: none; +} +.exportlink { + margin-bottom: 10px; + display: block; +} +.exporttype:before { + margin-right: 10px !important; +} + +/* hidden element */ +#importstatusball, +#importmessagesuccess, +#importmessageabiword { + display: none; +} + +#importmessageabiword { + color: #900; + font-size: small; +} + +#importsubmitinput { + margin-top: 10px; +} \ No newline at end of file diff --git a/src/static/css/pad/popup_users.css b/src/static/css/pad/popup_users.css new file mode 100644 index 00000000000..0832383f2db --- /dev/null +++ b/src/static/css/pad/popup_users.css @@ -0,0 +1,139 @@ +/* --------------- */ +/* --- LAYOUT ---- */ +/* --------------- */ + +.popup#users { + flex-direction: column; + max-height: 500px; + height: auto; +} +.popup#users #myuser { + flex-shrink: 0; +} +.popup#users #otherusers { + flex: 1 auto; + overflow: auto; + max-height: 200px; +} + +.popup#users.chatAndUsers { + display: flex !important; /* always visible */ + position: relative; + z-index: 1; + top: 0; + right: 0; + left: auto; +} +.popup#users.chatAndUsers > .popup-content { + border: none; + border-bottom: 1px solid #ccc; + border-left: 1px solid #ccc; + border-right: 0; + border-radius: 0; + box-shadow: none; + height: 200px; + min-width: 0; + padding: 5px; +} + + +/* --------------- */ +/* --- MY USER --- */ +/* --------------- */ + +#myswatchbox { + float: left; + width: 24px; + height: 24px; + border: 1px solid #ccc + background: transparent; + cursor: pointer; +} +#myswatch { + width: 100%; + height: 100%; + background: transparent; /*...initially*/ +} + +#myusernameform { + margin-left: 30px; +} +input#myusernameedit { + height: 26px; + font-size: 1.3em; + padding: 3px; + border: 1px solid #ccc; + background-color: transparent; + margin: 0; +} +input#myusernameedit:not(.editable) { + color: grey; +} +#myuser .myusernameedithoverable:hover { + background: white; +} +#myusernameform .editactive, +#myusernameform .editempty { + background: white; + border-left: 1px solid #c3c3c3; + border-top: 1px solid #c3c3c3; + border-right: 1px solid #e6e6e6; + border-bottom: 1px solid #e6e6e6; +} + +#myusernameedit, #otheruserstable .swatch { + border: 1px solid #ccc; +} +#myusernameform .editempty { + opacity: .8; +} + + +/* --------------------------- */ +/* --- MY USER COLORPICKER --- */ +/* --------------------------- */ + +#mycolorpicker.popup { + min-width: 0; + right: calc(100% + 15px); + z-index: 101; +} +@media (max-width: 720px) { + #mycolorpicker.popup { + top: auto; + bottom: 0; + left: auto !important; + right: 0 !important; + } +} +#mycolorpicker.popup .btn-container { + margin-top: 10px; +} +#mycolorpickerpreview { + width: 24px; + height: 24px; + border-radius: 5px; + float: right; +} + +/* ------------------- */ +/* --- OTHER USERS --- */ +/* ------------------- */ +#otheruserstable { + display: none; +} +#otheruserstable td { + height: 26px; + padding: 0 2px; +} +#otheruserstable .swatch { + border: 1px solid #ccc; + width: 13px; + height: 13px; + overflow: hidden; + margin: 0 4px; + user-select: none; +} +.usertdname { + font-size: 1.2rem; +} \ No newline at end of file diff --git a/src/static/css/pad/toolbar.css b/src/static/css/pad/toolbar.css new file mode 100644 index 00000000000..414a9e9097f --- /dev/null +++ b/src/static/css/pad/toolbar.css @@ -0,0 +1,175 @@ +.toolbar { + display: none; + position: relative; + background-color: #f4f4f4; + color: #666; + border-bottom: 1px solid #ccc; + overflow: hidden; + justify-content: space-between; + padding: 0px 5px 5px 5px; + flex-shrink: 0; +} +.toolbar ul { + list-style: none; + z-index: 2; + overflow: hidden; + margin: 0; + display: flex; + flex-direction: row; + align-items: flex-start; +} +.toolbar ul.menu_right { + flex-shrink: 0; /* prevent from shrinking */ +} +.toolbar ul li, .toolbar ul > div { + display: flex; /* transfer flexbox positionning to children */ +} +.toolbar ul li { + margin-top: 5px; /* when icons goes multi rows, have space betwwen each row */ +} +.toolbar ul li.separator { + visibility: hidden; + width: 10px; +} +.toolbar ul li a { + display: flex; + align-items: center; + justify-content: center; + min-width: 28px; + height: 28px; + border: 1px solid #ccc; + border-radius: 3px; + background: #fff; + cursor: pointer; + overflow: hidden; + text-decoration: none; + transition: background-color .1s; +} +.toolbar ul li button:active, .toolbar ul li button:focus { + outline: 0; + border: none; +} +.toolbar ul li a:hover { + text-decoration: none; + background-color: #f2f2f2; +} +.toolbar ul li a:active, .toolbar ul li a:focus { + background: #ddd; +} +.toolbar ul li a.selected { + background: #dadada; +} + +.toolbar ul li a.grouped-left { + border-radius: 3px 0 0 3px; +} +.toolbar ul li a.grouped-middle { + border-radius: 0; + border-left: 0; +} +.toolbar ul li a.grouped-right { + border-radius: 0 3px 3px 0; + border-left: 0; +} + +.toolbar ul li[data-key=showusers] > a { + min-width: 35px; +} +.toolbar ul li[data-key=showusers] > a .buttonicon-showusers { + padding-left: 3px; +} +.toolbar ul li[data-key=showusers] > a #online_count { + font-weight: bold; + font-size: 11px; + position: relative; + padding-left: 7px; +} + +.toolbar #toolbar-overlay { + z-index: 500; + display: none; + width: 100%; + position: absolute; + height: inherit; + left: 0; + top: 0; + bottom: 0; + right: 0; +} + +.toolbar .show-more-icon-btn { + display:none; + cursor: pointer; + height: 39px; + width: 39px; + line-height: 39px; + text-align: center; + font-weight: bold; + font-size: 2rem; + z-index: 20; +} + +.toolbar.cropped .menu_left { + width: calc(100% - 39px); + height: 33px; + flex-wrap: wrap; +} +.toolbar.cropped .show-more-icon-btn { + display: block; + position: absolute; + /*border-bottom: 1px solid #d2d2d2;*/ + right: 0; + top: 0; +} +.toolbar.cropped .show-more-icon-btn:after { + content: "+"; +} +.toolbar.full-icons .show-more-icon-btn { + line-height: 35px; +} +.toolbar.full-icons .show-more-icon-btn:after { + content: "-"; +} +.toolbar.full-icons .menu_left { + height: auto !important; + overflow: visible; +} + +@media only screen and (max-width: 720px) { + .toolbar ul li.separator { + width: 5px; + } + /* menu_right act like a new toolbar on the bottom of the screen */ + .toolbar .menu_right { + position: fixed; + bottom: 0; + right: 0; + left: 0; + border-top: 1px solid #ccc; + background-color: #f4f4f4; + padding: 0 5px 5px 5px; + } + .toolbar ul.menu_right > li { + margin-right: 8px; + } + .toolbar ul.menu_right > li.separator { + display: none; + } + .toolbar ul.menu_right > li a { + border: none; + background-color: transparent; + margin-left: 5px; + } + .toolbar ul.menu_right > li[data-key="showusers"] { + position: absolute; + right: 0; + top: 0; + bottom: 0; + margin: 0; + } + .toolbar ul.menu_right > li[data-key="showusers"] a { + height: 100%; + width: 40px; + border-radius: 0; + } +} \ No newline at end of file diff --git a/src/static/css/timeslider.css b/src/static/css/timeslider.css index 0311b10eeb8..cf3cbff04f0 100644 --- a/src/static/css/timeslider.css +++ b/src/static/css/timeslider.css @@ -1,279 +1,153 @@ -@import url('./lists_and_indents.css'); - -p.pblort { - height: 100px; -} - -#editorcontainerbox { - overflow: auto; - top: 40px; - position: static; -} -#padcontent { - font-size: 12px; +#editbar { padding: 10px; + display: block; } -#timeslider-wrapper { - left: 0; - position: relative; - right: 0; - top: 0; +#innerdocbody { + margin: 0 auto; } -#timeslider-left { - background-color:#fff; - height: 63px; - left: 0; - position: absolute; - width: 134px; -} -#timeslider-right { - background-color:#fff; - height: 63px; - position: absolute; - right: 0; - top: 0; - width: 155px; -} -#timeslider { - height: 63px; - margin: 0 9px; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-color:#fff; - /* bgcolor is reuqired so you can't see pad content behind it */ -} -#timeslider #timeslider-slider { - height: 61px; - left: 0; - position: absolute; - top: 1px; - width: 100%; -} -#ui-slider-handle { - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - background-color: #666; - cursor: pointer; - height: 61px; - left: 0; - position: absolute; - top: 0; - width: 13px; -} -#ui-slider-bar { - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; - cursor: pointer; - height: 60px; - margin-left: 5px; - margin-right: 150px; - position: relative; - top: 0px; + +.timeslider-bar { + display: flex; + flex-direction: row; } -#playpause_button, -#playpause_button_icon { - height: 44px; - position: absolute; - width: 44px; - text-align:center; - vertical-align:middle; - background:none; +/* TITLE */ + +.timeslider-title-container { + flex: 1 auto; } -#playpause_button { - right: 77px; - top: 9px; - height:50px; - height:50px; - background: background-linear-gradient( #F7F7F7, #F1F1F1 80%) repeat scroll 0 0 transparent; - border-radius:24px; - cursor:hand; +.timeslider-title { + font-size: 1.8rem !important; } -#playpause_button_icon:before { - line-height:44px; - padding-left:2px; - font-family: fontawesome-etherpad; - content: "\e82c"; - font-size:24px; - color:#666; +.timeslider-subtitle { + margin-top: 10px; } -#playpause_button_icon { - left: 0; - top: 0; - border-radius:48px; - border: solid 1px #666; -} -.pause:before { - line-height:44px; - padding-left:2px; - font-family: fontawesome-etherpad; - content: "\e82e" !important; - font-size:24px; - color:#666; - padding-left:0 !important; -} -#leftstar, -#rightstar, -#leftstep, -#rightstep { - background-color: white; - overflow: hidden; - position: absolute; +/* RIGHT TOOLBAR (export, settings, back to pad) */ + +.editbarright ul li a { + background-color: transparent; + border: none; + margin-left: 10px } -.stepper{ - font-family: fontawesome-etherpad; - border-radius:2px; - border: #666 solid 1px; -/* line-height:18px; */ - text-align:center; - height:22px; - color:#666; + +/* SLIDER */ + +#timeslider-wrapper { + display: flex; + flex-direction: row; + height: 40px; } -stepper:active{ - color:#000; +#timeslider-slider { + flex: 1 auto; + display: flex; + flex-direction: column; + justify-content: center; + cursor: pointer; + position: relative; } -#leftstep { - right: 38px; - top: 20px; - width: 25px; +#timeslider-slider #timer { + position: absolute; + top: -10px; + right: -10px; } -#leftstep:before{ - content: '\e821'; - vertical-align:middle; + +#timeslider-slider #ui-slider-bar { + height: 10px; + width: 100%; + background-color: #c2c2c2; + position: relative; } -#rightstep:before{ - content: "\e822"; - vertical-align:middle; + +#timeslider-slider #ui-slider-handle { + height: 40px; + width: 10px; + z-index: 2; + position: absolute; + background-color: #3e3e3e; + cursor: move; } -#rightstep { - right: 12px; - top: 20px; - width: 25px; +#timeslider-slider .star { + cursor: pointer; + position: absolute; + top: -8px } -.star:before{ +#timeslider-slider .star:before{ font-family: fontawesome-etherpad; - content: "\e835"; + color: #da9700; + content: "\e856"; vertical-align:middle; font-size:16px; + margin-left: -2px; } -#timeslider .star { - cursor: pointer; - height: 16px; - position: absolute; - top: 25px; - width: 15px; -} -#timeslider #timer { - background: linear-gradient(#F7F7F7, #F1F1F1 80%) repeat scroll 0% 0% transparent; - padding:2px; - border-radius:2px; - font-family: Arial, sans-serif; - font-size: 11px; - left: 7px; - position: absolute; - text-align: center; - top: 9px; - width: 122px; -} -.topbarcenter, -#docbar { - display: none -} -#padmain { - top: 0px !important -} -#editbar{ - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} -.editbarright { - float: right; - text-align: right; - height: 30px !important; -} -.toolbar ul{ - position:relative; - float:right; - height:30px; -} -#import_export, #settings{ - top: 115px; - position: fixed; -} -#import_export .popup { - width: 183px; - border-top: none; - border-right: none; - border-radius: 0 0 0 6px; + +/* BUTTONS TO MOVE SLIDER (Play/Pause, Next, Prev)*/ + +#slider-btn-container { + margin-left: 15px; + display: flex; + align-items: center; } -#import_export { - width: 185px; +#slider-btn-container button { + border: 1px solid #666; + border-radius: 50%; + width: 30px; + height: 30px; + margin-left: 5px; } -.timeslider-bar { - background: #f7f7f7; - background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -moz-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -o-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%); - background: linear-gradient(#f7f7f7, #f1f1f1 80%); - overflow: hidden; - padding-top: 3px; - width: 100%; +#slider-btn-container #playpause_button_icon { + width: 40px; + height: 40px; + padding-left: 2px; } -.timeslider-bar #editbar { - border-bottom: none; - float: right; - width: auto; +#slider-btn-container #playpause_button_icon:before { + font-size: 22px; } -.timeslider-bar h1 { - margin: 5px +#slider-btn-container #playpause_button_icon.pause:before { + content: "\e829"; + padding-left: 0; + padding-right: 2px; } -.timeslider-bar p { - margin: 5px + + +/* PAD CONTENT */ + +#editorcontainerbox { + overflow-y: auto; } -#timeslider-top { +#outerdocbody { + display: block; width: 100%; - position: fixed; - z-index: 1; -} -#authorsList .author { - padding-left: 0.4em; - padding-right: 0.4em; -} -#authorsList .author-anonymous { - padding-left: 0.6em; - padding-right: 0.6em; -} -#padeditor { - position: static } -button{ - margin:0; - padding:0; - cursor:pointer; +#innerdocbody { + white-space: normal; + word-break: break-word; + width: 100%; + height: 100%; } -button::-moz-focus-inner { - padding: 0; - border: 0 -} +@media (max-width: 720px) { + #timeslider-slider #timer { display: none; } -button:focus{ - border: 1px solid #666; -} + .editbarright [data-key="timeslider_returnToPad"] { + position: absolute; + right: 10px; + top: 0; + } + .timeslider-title { + font-size: 1.5rem !important; + } + .timeslider-title-container { + width: 100%; + } + .authors-label { display: none; } + #authorsList { + display: flex; + flex-wrap: wrap; + } +} \ No newline at end of file diff --git a/src/static/favicon.ico b/src/static/favicon.ico index 938e9550240..c33f2e614c6 100644 Binary files a/src/static/favicon.ico and b/src/static/favicon.ico differ diff --git a/src/static/font/Montserrat-Light.otf b/src/static/font/Montserrat-Light.otf old mode 100755 new mode 100644 diff --git a/src/static/font/Montserrat-Regular.otf b/src/static/font/Montserrat-Regular.otf old mode 100755 new mode 100644 diff --git a/src/static/font/Quicksand-Bold.ttf b/src/static/font/Quicksand-Bold.ttf new file mode 100644 index 00000000000..49326cda826 Binary files /dev/null and b/src/static/font/Quicksand-Bold.ttf differ diff --git a/src/static/font/Quicksand-Medium.ttf b/src/static/font/Quicksand-Medium.ttf new file mode 100644 index 00000000000..7dc8c2745dd Binary files /dev/null and b/src/static/font/Quicksand-Medium.ttf differ diff --git a/src/static/font/Quicksand-Regular.ttf b/src/static/font/Quicksand-Regular.ttf new file mode 100644 index 00000000000..9fdce17db50 Binary files /dev/null and b/src/static/font/Quicksand-Regular.ttf differ diff --git a/src/static/font/Roboto-Bold.ttf b/src/static/font/Roboto-Bold.ttf new file mode 100644 index 00000000000..d998cf5b468 Binary files /dev/null and b/src/static/font/Roboto-Bold.ttf differ diff --git a/src/static/font/Roboto-Regular.ttf b/src/static/font/Roboto-Regular.ttf new file mode 100644 index 00000000000..2b6392ffe87 Binary files /dev/null and b/src/static/font/Roboto-Regular.ttf differ diff --git a/src/static/font/RobotoMono-Bold.ttf b/src/static/font/RobotoMono-Bold.ttf old mode 100755 new mode 100644 diff --git a/src/static/font/RobotoMono-Regular.ttf b/src/static/font/RobotoMono-Regular.ttf old mode 100755 new mode 100644 diff --git a/src/static/font/config.json b/src/static/font/config.json index 1c636281da4..31f516d2cd1 100644 --- a/src/static/font/config.json +++ b/src/static/font/config.json @@ -1,6 +1,6 @@ { "name": "fontawesome-etherpad", - "css_prefix_text": "icon-", + "css_prefix_text": "buttonicon-", "css_use_suffix": false, "hinting": true, "units_per_em": 1000, @@ -12,330 +12,18 @@ "code": 59402, "src": "fontawesome" }, - { - "uid": "474656633f79ea2f1dad59ff63f6bf07", - "css": "star", - "code": 59446, - "src": "fontawesome" - }, - { - "uid": "d17030afaecc1e1c22349b99f3c4992a", - "css": "star-empty", - "code": 59445, - "src": "fontawesome" - }, - { - "uid": "8b80d36d4ef43889db10bc1f0dc9a862", - "css": "user", - "code": 59401, - "src": "fontawesome" - }, - { - "uid": "31972e4e9d080eaa796290349ae6c1fd", - "css": "users", - "code": 59400, - "src": "fontawesome" - }, - { - "uid": "0f99ab40ab0b4d64a74f2d0deeb03e42", - "css": "videocam", - "code": 59403, - "src": "fontawesome" - }, - { - "uid": "381da2c2f7fd51f8de877c044d7f439d", - "css": "picture", - "code": 59404, - "src": "fontawesome" - }, - { - "uid": "7fd683b2c518ceb9e5fa6757f2276faa", - "css": "eye-off", - "code": 59405, - "src": "fontawesome" - }, - { - "uid": "7034e4d22866af82bef811f52fb1ba46", - "css": "code", - "code": 59431, - "src": "fontawesome" - }, { "uid": "7277ded7695b2a307a5f9d50097bb64c", "css": "print", "code": 59393, "src": "fontawesome" }, - { - "uid": "85528017f1e6053b2253785c31047f44", - "css": "comment", - "code": 59448, - "src": "fontawesome" - }, - { - "uid": "dcedf50ab1ede3283d7a6c70e2fe32f3", - "css": "chat", - "code": 59432, - "src": "fontawesome" - }, - { - "uid": "9c1376672bb4f1ed616fdd78a23667e9", - "css": "comment-empty", - "code": 59433, - "src": "fontawesome" - }, - { - "uid": "f48ae54adfb27d8ada53d0fd9e34ee10", - "css": "trash-empty", - "code": 59434, - "src": "fontawesome" - }, - { - "uid": "1b5a5d7b7e3c71437f5a26befdd045ed", - "css": "doc", - "code": 59394, - "src": "fontawesome" - }, - { - "uid": "9daa1fdf0838118518a7e22715e83abc", - "css": "file-pdf", - "code": 59395, - "src": "fontawesome" - }, - { - "uid": "310ffd629da85142bc8669f010556f2d", - "css": "file-word", - "code": 59396, - "src": "fontawesome" - }, - { - "uid": "f761c3bbe16ba2d332914ecb28e7a042", - "css": "file-excel", - "code": 59397, - "src": "fontawesome" - }, - { - "uid": "edcd4022de8d8df266ef7c42d2658ca5", - "css": "file-powerpoint", - "code": 59398, - "src": "fontawesome" - }, - { - "uid": "3c961c1a8d874815856fc6637dc5a13c", - "css": "file-image", - "code": 59399, - "src": "fontawesome" - }, - { - "uid": "26613a2e6bc41593c54bead46f8c8ee3", - "css": "file-code", - "code": 59430, - "src": "fontawesome" - }, - { - "uid": "e99461abfef3923546da8d745372c995", - "css": "cog", - "code": 59443, - "src": "fontawesome" - }, - { - "uid": "19c50c52858a81de58f9db488aba77bc", - "css": "mic", - "code": 59435, - "src": "fontawesome" - }, - { - "uid": "598a5f2bcf3521d1615de8e1881ccd17", - "css": "clock", - "code": 59447, - "src": "fontawesome" - }, - { - "uid": "bc71f4c6e53394d5ba46b063040014f1", - "css": "cw", - "code": 59428, - "src": "fontawesome" - }, - { - "uid": "f9c3205df26e7778abac86183aefdc99", - "css": "ccw", - "code": 59427, - "src": "fontawesome" - }, - { - "uid": "a73c5deb486c8d66249811642e5d719a", - "css": "arrows-cw", - "code": 59429, - "src": "fontawesome" - }, - { - "uid": "6020aff067fc3c119cdd75daa5249220", - "css": "exchange", - "code": 59444, - "src": "fontawesome" - }, - { - "uid": "ce06b5805120d0c2f8d60cd3f1a4fdb5", - "css": "play", - "code": 59436, - "src": "fontawesome" - }, - { - "uid": "b624a1e512819d410ddbee84e6918b9d", - "css": "stop", - "code": 59437, - "src": "fontawesome" - }, - { - "uid": "0b28050bac9d3facf2f0226db643ece0", - "css": "pause", - "code": 59438, - "src": "fontawesome" - }, - { - "uid": "c47efa0e3e74f6ba4c2562c1258fff1f", - "css": "to-end", - "code": 59426, - "src": "fontawesome" - }, - { - "uid": "12052b30d23a1a70d6b32962d5464cae", - "css": "to-start", - "code": 59425, - "src": "fontawesome" - }, - { - "uid": "f9cbf7508cd04145ade2800169959eef", - "css": "font", - "code": 59419, - "src": "fontawesome" - }, - { - "uid": "02cca871bb69da75e8ee286b7055832c", - "css": "bold", - "code": 59420, - "src": "fontawesome" - }, - { - "uid": "a8cb1c217f02b073db3670c061cc54d2", - "css": "italic", - "code": 59421, - "src": "fontawesome" - }, - { - "uid": "0c708edd8fae2376b3370aa56d40cf9e", - "css": "header", - "code": 59422, - "src": "fontawesome" - }, - { - "uid": "c009d417f87d6a27bb5a1cefd30b6cbd", - "css": "text-height", - "code": 59423, - "src": "fontawesome" - }, - { - "uid": "13a971bcccd2dda26d4d4eccd8593f8a", - "css": "text-width", - "code": 59424, - "src": "fontawesome" - }, - { - "uid": "f4f0e849b805be1f6d76b65581cb3b8b", - "css": "align-left", - "code": 59392, - "src": "fontawesome" - }, - { - "uid": "ae6336c46d73af999fe7460c089abb4d", - "css": "align-center", - "code": 59407, - "src": "fontawesome" - }, - { - "uid": "e1e7306b47c3c5e6faecce9d32571381", - "css": "align-right", - "code": 59408, - "src": "fontawesome" - }, - { - "uid": "25a81737628d1e654a30ad412d7d6dd7", - "css": "align-justify", - "code": 59409, - "src": "fontawesome" - }, - { - "uid": "48b87105bd38c20315f1b705b8c7b38c", - "css": "list", - "code": 59410, - "src": "fontawesome" - }, - { - "uid": "594e9271c08ff732c04b3bf3117b9040", - "css": "indent-left", - "code": 59411, - "src": "fontawesome" - }, - { - "uid": "4d2dfc45d8176b1f26aed973fa84a91e", - "css": "indent-right", - "code": 59412, - "src": "fontawesome" - }, - { - "uid": "a2a74f5e7b7d9ba054897d8c795a326a", - "css": "list-bullet", - "code": 59413, - "src": "fontawesome" - }, - { - "uid": "f6766a8b042c2453a4e153af03294383", - "css": "list-numbered", - "code": 59414, - "src": "fontawesome" - }, - { - "uid": "61c242c9e2134d5864d7fdd57b3c9289", - "css": "strike", - "code": 59416, - "src": "fontawesome" - }, - { - "uid": "d4a4a38a40b728f46dad1de4ac950231", - "css": "underline", - "code": 59415, - "src": "fontawesome" - }, - { - "uid": "4e88371fb8857dacc1f66afe6314e426", - "css": "superscript", - "code": 59417, - "src": "fontawesome" - }, - { - "uid": "3d1c929dbc966992185ce749548c1b2c", - "css": "subscript", - "code": 59418, - "src": "fontawesome" - }, { "uid": "9396b2d8849e0213a0f11c5fd7fcc522", "css": "tasks", "code": 59442, "src": "fontawesome" }, - { - "uid": "0bda4bc779d4c32623dec2e43bd67ee8", - "css": "gauge", - "code": 59439, - "src": "fontawesome" - }, - { - "uid": "cda0cdcfd38f5f1d9255e722dad42012", - "css": "spinner", - "code": 59406, - "src": "fontawesome" - }, { "uid": "fa9a0b7e788c2d78e24cef1de6b70e80", "css": "brush", @@ -354,17 +42,815 @@ "code": 59449, "src": "fontawesome" }, - { - "uid": "0ddd3e8201ccc7d41f7b7c9d27eca6c1", - "css": "link", - "code": 59450, - "src": "fontawesome" - }, { "uid": "8fb55fd696d9a0f58f3b27c1d8633750", "css": "table", "code": 61646, "src": "fontawesome" + }, + { + "uid": "1569a5b2bebe7e28bb0d26ddeca34fc8", + "css": "video", + "code": 59451, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M656.6 125H93.4C41.8 125 0 166.8 0 218.4V781.6C0 833.2 41.8 875 93.4 875H656.6C708.2 875 750 833.2 750 781.6V218.4C750 166.8 708.2 125 656.6 125ZM1026.6 198.6L812.5 346.3V653.7L1026.6 801.2C1068 829.7 1125 800.6 1125 750.8V249C1125 199.4 1068.2 170.1 1026.6 198.6Z", + "width": 1125 + }, + "search": [ + "video" + ] + }, + { + "uid": "8fe2c571b78d019e24cab0b780cb61d6", + "css": "video-slash", + "code": 59452, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M1237.9 894.7L1130.5 811.7C1160.5 809 1187.5 785 1187.5 751V249C1187.5 199.2 1130.7 170.1 1089.1 198.6L875 346.3V614.3L812.5 566V218.4C812.5 166.8 770.7 125 719.1 125H242L88.9 6.6C75.2-3.9 55.7-1.6 44.9 12.1L6.6 61.3C-3.9 75-1.6 94.5 12.1 105.1L83.4 160.2 812.5 723.8 1161.1 993.4C1174.8 1003.9 1194.3 1001.6 1205.1 987.9L1243.4 938.5C1254.1 925 1251.6 905.3 1237.9 894.7ZM62.5 781.6C62.5 833.2 104.3 875 155.9 875H719.1C741 875 760.9 867.2 777 854.5L62.5 302.1V781.6Z", + "width": 1250 + }, + "search": [ + "video-slash" + ] + }, + { + "uid": "d8020fccc088a524f7cc6db1f329cb3e", + "css": "microphone-alt", + "code": 59453, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M656.3 375H625C607.7 375 593.8 389 593.8 406.3V500C593.8 646.1 467.8 763.3 318.8 748.8 188.9 736.1 93.8 619.4 93.8 488.9V406.3C93.8 389 79.8 375 62.5 375H31.3C14 375 0 389 0 406.3V484.7C0 659.8 124.9 815.8 296.9 839.6V906.3H187.5C170.2 906.3 156.3 920.2 156.3 937.5V968.8C156.3 986 170.2 1000 187.5 1000H500C517.3 1000 531.3 986 531.3 968.8V937.5C531.3 920.2 517.3 906.3 500 906.3H390.6V840.3C558 817.3 687.5 673.6 687.5 500V406.3C687.5 389 673.5 375 656.3 375ZM343.8 687.5C447.3 687.5 531.3 603.6 531.3 500H364.6C353.1 500 343.8 493 343.8 484.4V453.1C343.8 444.5 353.1 437.5 364.6 437.5H531.3V375H364.6C353.1 375 343.8 368 343.8 359.4V328.1C343.8 319.5 353.1 312.5 364.6 312.5H531.3V250H364.6C353.1 250 343.8 243 343.8 234.4V203.1C343.8 194.5 353.1 187.5 364.6 187.5H531.3C531.3 83.9 447.3 0 343.8 0S156.3 83.9 156.3 187.5V500C156.3 603.6 240.2 687.5 343.8 687.5Z", + "width": 688 + }, + "search": [ + "microphone-alt" + ] + }, + { + "uid": "7d9dd931e0e6305cc5eed55efa435d7c", + "css": "microphone-alt-slash", + "code": 59454, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M1237.9 894.7L930.2 656.9C954.6 609.8 968.8 556.6 968.8 500V406.3C968.8 389 954.8 375 937.5 375H906.3C889 375 875 389 875 406.3V500C875 535 867.3 568 854.1 598L802.2 558C808.3 539.6 812.5 520.4 812.5 500H727.2L646.4 437.5H812.5V375H645.8C634.3 375 625 368 625 359.4V328.1C625 319.5 634.3 312.5 645.8 312.5H812.5V250H645.8C634.3 250 625 243 625 234.4V203.1C625 194.5 634.3 187.5 645.8 187.5H812.5C812.5 84 728.6 0 625 0S437.5 84 437.5 187.5V276.1L88.8 6.6C75.2-4 55.5-1.6 44.9 12.1L6.6 61.4C-4 75-1.6 94.7 12.1 105.3L1161.2 993.4C1174.8 1004 1194.5 1001.6 1205.1 987.9L1243.4 938.6C1254 925 1251.6 905.3 1237.9 894.7ZM781.3 906.3H671.9V840.3C694.7 837.1 717 831.9 738.2 824.5L639.8 748.4C626.7 749.2 613.6 750.1 600 748.8 490.9 738.1 407.2 653.8 382.9 549.9L281.3 471.3V484.7C281.3 659.8 406.2 815.8 578.1 839.6V906.3H468.8C451.5 906.3 437.5 920.2 437.5 937.5V968.8C437.5 986 451.5 1000 468.8 1000H781.3C798.5 1000 812.5 986 812.5 968.8V937.5C812.5 920.2 798.5 906.3 781.3 906.3Z", + "width": 1250 + }, + "search": [ + "microphone-alt-slash" + ] + }, + { + "uid": "63aa8ba99d3f31973dd2ef65274a03bd", + "css": "compress", + "code": 59455, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M851.6 375H609.4C583.4 375 562.5 354.1 562.5 328.1V85.9C562.5 73 573 62.5 585.9 62.5H664.1C677 62.5 687.5 73 687.5 85.9V250H851.6C864.5 250 875 260.5 875 273.4V351.6C875 364.5 864.5 375 851.6 375ZM312.5 328.1V85.9C312.5 73 302 62.5 289.1 62.5H210.9C198 62.5 187.5 73 187.5 85.9V250H23.4C10.5 250 0 260.5 0 273.4V351.6C0 364.5 10.5 375 23.4 375H265.6C291.6 375 312.5 354.1 312.5 328.1ZM312.5 914.1V671.9C312.5 645.9 291.6 625 265.6 625H23.4C10.5 625 0 635.5 0 648.4V726.6C0 739.5 10.5 750 23.4 750H187.5V914.1C187.5 927 198 937.5 210.9 937.5H289.1C302 937.5 312.5 927 312.5 914.1ZM687.5 914.1V750H851.6C864.5 750 875 739.5 875 726.6V648.4C875 635.5 864.5 625 851.6 625H609.4C583.4 625 562.5 645.9 562.5 671.9V914.1C562.5 927 573 937.5 585.9 937.5H664.1C677 937.5 687.5 927 687.5 914.1Z", + "width": 875 + }, + "search": [ + "compress" + ] + }, + { + "uid": "d71c270fcbdffa89ee7b646e9d5a2667", + "css": "expand", + "code": 59456, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M0 351.6V109.4C0 83.4 20.9 62.5 46.9 62.5H289.1C302 62.5 312.5 73 312.5 85.9V164.1C312.5 177 302 187.5 289.1 187.5H125V351.6C125 364.5 114.5 375 101.6 375H23.4C10.5 375 0 364.5 0 351.6ZM562.5 85.9V164.1C562.5 177 573 187.5 585.9 187.5H750V351.6C750 364.5 760.5 375 773.4 375H851.6C864.5 375 875 364.5 875 351.6V109.4C875 83.4 854.1 62.5 828.1 62.5H585.9C573 62.5 562.5 73 562.5 85.9ZM851.6 625H773.4C760.5 625 750 635.5 750 648.4V812.5H585.9C573 812.5 562.5 823 562.5 835.9V914.1C562.5 927 573 937.5 585.9 937.5H828.1C854.1 937.5 875 916.6 875 890.6V648.4C875 635.5 864.5 625 851.6 625ZM312.5 914.1V835.9C312.5 823 302 812.5 289.1 812.5H125V648.4C125 635.5 114.5 625 101.6 625H23.4C10.5 625 0 635.5 0 648.4V890.6C0 916.6 20.9 937.5 46.9 937.5H289.1C302 937.5 312.5 927 312.5 914.1Z", + "width": 875 + }, + "search": [ + "expand" + ] + }, + { + "uid": "5d2d07f112b8de19f2c0dbfec3e42c05", + "css": "spin5", + "code": 59457, + "src": "fontelico" + }, + { + "uid": "54cecf7a3401a3458fe7ea001e622d39", + "css": "trash", + "code": 59406, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M843.8 62.5H609.4L591 26A46.9 46.9 0 0 0 549 0H325.8A46.3 46.3 0 0 0 284 26L265.6 62.5H31.3A31.3 31.3 0 0 0 0 93.8V156.3A31.3 31.3 0 0 0 31.3 187.5H843.8A31.3 31.3 0 0 0 875 156.3V93.8A31.3 31.3 0 0 0 843.8 62.5ZM103.9 912.1A93.8 93.8 0 0 0 197.5 1000H677.5A93.8 93.8 0 0 0 771.1 912.1L812.5 250H62.5Z", + "width": 875 + }, + "search": [ + "trash" + ] + }, + { + "uid": "f99ec3e571ced9cd747e2b34d8c03436", + "css": "list-ul", + "code": 59434, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M187.5 187.5C187.5 239.3 145.5 281.3 93.8 281.3S0 239.3 0 187.5 42 93.8 93.8 93.8 187.5 135.7 187.5 187.5ZM93.8 406.3C42 406.3 0 448.2 0 500S42 593.8 93.8 593.8 187.5 551.8 187.5 500 145.5 406.3 93.8 406.3ZM93.8 718.8C42 718.8 0 760.7 0 812.5S42 906.3 93.8 906.3 187.5 864.3 187.5 812.5 145.5 718.8 93.8 718.8ZM281.3 257.8H968.8C986 257.8 1000 243.8 1000 226.6V148.4C1000 131.2 986 117.2 968.8 117.2H281.3C264 117.2 250 131.2 250 148.4V226.6C250 243.8 264 257.8 281.3 257.8ZM281.3 570.3H968.8C986 570.3 1000 556.3 1000 539.1V460.9C1000 443.7 986 429.7 968.8 429.7H281.3C264 429.7 250 443.7 250 460.9V539.1C250 556.3 264 570.3 281.3 570.3ZM281.3 882.8H968.8C986 882.8 1000 868.8 1000 851.6V773.4C1000 756.2 986 742.2 968.8 742.2H281.3C264 742.2 250 756.2 250 773.4V851.6C250 868.8 264 882.8 281.3 882.8Z", + "width": 1000 + }, + "search": [ + "list-ul" + ] + }, + { + "uid": "d921283a409a4e9a51ff1632b200c23d", + "css": "eye-slash", + "code": 59459, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M625 781.3C476.9 781.3 356.9 666.6 345.9 521.3L141 362.9C114.1 396.7 89.3 432.4 69.3 471.5A63.2 63.2 0 0 0 69.3 528.5C175.2 735.2 384.9 875 625 875 677.6 875 728.3 867.2 777.1 854.6L675.8 776.2A281.5 281.5 0 0 1 625 781.3ZM1237.9 894.7L1022 727.9A647 647 0 0 0 1180.7 528.5 63.2 63.2 0 0 0 1180.7 471.5C1074.8 264.8 865.1 125 625 125A601.9 601.9 0 0 0 337.3 198.6L88.8 6.6A31.3 31.3 0 0 0 44.9 12.1L6.6 61.4A31.3 31.3 0 0 0 12.1 105.3L1161.2 993.4A31.3 31.3 0 0 0 1205.1 987.9L1243.4 938.6A31.3 31.3 0 0 0 1237.9 894.7ZM879.1 617.4L802.3 558A185.1 185.1 0 0 0 812.5 500 185.1 185.1 0 0 0 575.6 319.9 93.1 93.1 0 0 1 593.8 375 91.1 91.1 0 0 1 590.7 394.5L447 283.4A277.9 277.9 0 0 1 625 218.8 281.1 281.1 0 0 1 906.3 500C906.3 542.2 895.9 581.6 879.1 617.4Z", + "width": 1250 + }, + "search": [ + "eye-slash" + ] + }, + { + "uid": "9f79bb02a62542500d6396747bfbdad5", + "css": "list-ol", + "code": 59460, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M6.4 272.5C6.4 257.9 14 249.9 29 249.9H58.5V172C58.5 161.9 59.6 151.5 59.6 151.5H58.9S55.4 156.7 53.3 158.8C44.6 167.2 32.8 167.5 22.7 156.7L11.9 144.6C1.5 134.1 2.2 122.7 13 112.6L55.4 73.6C64.1 65.6 71.7 62.5 83.6 62.5H107.2C122.2 62.5 130.2 70.1 130.2 85.1V249.9H160.4C175.4 249.9 183 257.9 183 272.5V289.9C183 304.5 175.4 312.5 160.4 312.5H29C14 312.5 6.4 304.5 6.4 289.9V272.5ZM4.3 594.9C4.3 502.6 103.8 484.8 103.8 459.8 103.8 445.8 92.2 442.7 85.7 442.7 79.6 442.7 73.1 444.8 67.2 450.2 57.3 459.8 46.7 463.9 35.8 455L19 441.7C7.7 432.8 5 422.5 13.6 411.6 26.5 394.5 50.8 375 92.6 375 130.5 375 179.4 395.5 179.4 452.3 179.4 527.2 88.1 542.9 84.3 563.4H160.6C175.3 563.4 183.2 571.3 183.2 585.7V602.8C183.2 617.1 175.3 625 160.6 625H27.9C14.2 625 4.3 617.1 4.3 602.8V594.9ZM11 887.9L22 869.8C29.5 856.8 39.8 856.1 52.4 863.6 62 867.7 71.2 869.8 80.5 869.8 100.3 869.8 108.5 862.9 108.5 853.7 108.5 840.7 97.6 835.9 77.4 835.9H68.2C56.5 835.9 50 831.8 44.2 820.5L42.2 816.8C37.4 807.5 39.8 797.6 47.6 787.7L58.6 774C71.9 757.6 82.5 747.7 82.5 747.7V747S74.3 749.1 57.9 749.1H32.6C17.9 749.1 10.4 741.2 10.4 726.8V709.7C10.4 695 17.9 687.5 32.6 687.5H146.8C161.5 687.5 169 695.4 169 709.7V716.2C169 727.5 166.3 735.4 159.1 743.9L124.9 783.3C163.2 793.2 181 823.3 181 851.3 181 893 153 937.5 86.3 937.5 53.8 937.5 31.2 928.3 16.2 919 4.9 910.8 3.9 899.9 11 887.9ZM281.3 257.8H968.8C986 257.8 1000 243.8 1000 226.6V148.4C1000 131.2 986 117.2 968.8 117.2H281.3C264 117.2 250 131.2 250 148.4V226.6C250 243.8 264 257.8 281.3 257.8ZM281.3 570.3H968.8C986 570.3 1000 556.3 1000 539.1V460.9C1000 443.7 986 429.7 968.8 429.7H281.3C264 429.7 250 443.7 250 460.9V539.1C250 556.3 264 570.3 281.3 570.3ZM281.3 882.8H968.8C986 882.8 1000 868.8 1000 851.6V773.4C1000 756.2 986 742.2 968.8 742.2H281.3C264 742.2 250 756.2 250 773.4V851.6C250 868.8 264 882.8 281.3 882.8Z", + "width": 1000 + }, + "search": [ + "list-ol" + ] + }, + { + "uid": "216f7d72d19fbfc4e319fe70240dc9fe", + "css": "bold", + "code": 59461, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M595.3 476.3C661 440.1 700.1 370.6 700.1 289.4 700.1 195.2 648.8 118.3 566.1 86 517.8 66.4 470.4 62.5 409.5 62.5H46.9C29.6 62.5 15.6 76.5 15.6 93.8V158.3C15.6 175.6 29.6 189.5 46.9 189.5H111.5V811.7H46.9C29.6 811.7 15.6 825.7 15.6 842.9V906.3C15.6 923.5 29.6 937.5 46.9 937.5H429.1C476.4 937.5 516.6 935 559.7 922.7 659.2 893 734.4 802 734.4 683.6 734.4 581.7 682.5 504.6 595.3 476.3ZM277.8 196.9H409.5C441.3 196.9 463.3 200.8 482.8 210 513.7 226.6 531.4 261.8 531.4 306.6 531.4 375 491.7 417.5 427.9 417.5H277.8V196.9ZM497.8 793.5C478 801.4 453.5 803.1 436.4 803.1H277.8V550.7H442.5C520 550.7 565.7 600.2 565.7 673.8 565.7 729.3 539 776.3 497.8 793.5Z", + "width": 750 + }, + "search": [ + "bold" + ] + }, + { + "uid": "0dbd89c5def7ede2cbbe99ef8effcbda", + "css": "underline", + "code": 59462, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M438 758.3C259 758.3 132.2 658.3 132.2 462.6V125H76.9C59.6 125 45.6 111 45.6 93.8V31.3C45.6 14 59.6 0 76.9 0H345.2C362.5 0 376.5 14 376.5 31.3V93.8C376.5 111 362.5 125 345.2 125H289V462.6C289 567.5 344.3 617.8 438 617.8 529.7 617.8 586.1 568.1 586.1 461.6V125H530.8C513.5 125 499.5 111 499.5 93.8V31.3C499.5 14 513.5 0 530.8 0H798.1C815.4 0 829.4 14 829.4 31.3V93.8C829.4 111 815.4 125 798.1 125H742.9V462.6C742.9 656.7 616.1 758.3 438 758.3ZM31.3 875H843.8C861 875 875 889 875 906.3V968.8C875 986 861 1000 843.8 1000H31.3C14 1000 0 986 0 968.8V906.3C0 889 14 875 31.3 875Z", + "width": 875 + }, + "search": [ + "underline" + ] + }, + { + "uid": "daa7f27064d8c218bf22731012103675", + "css": "italic", + "code": 59463, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M399.9 812.5H333.8L455.1 187.5H534.6A31.3 31.3 0 0 0 565.3 162.2L577.5 99.7C581.2 80.4 566.5 62.5 546.8 62.5H234.8A31.3 31.3 0 0 0 204.2 87.8L192 150.3C188.2 169.6 203 187.5 222.6 187.5H288.7L167.5 812.5H90.4A31.3 31.3 0 0 0 59.7 837.8L47.5 900.3C43.8 919.6 58.5 937.5 78.2 937.5H387.7A31.3 31.3 0 0 0 418.4 912.2L430.6 849.7C434.4 830.4 419.6 812.5 399.9 812.5Z", + "width": 625 + }, + "search": [ + "italic" + ] + }, + { + "uid": "638e629bf04f06f100d42a3b6c3afeaa", + "css": "strikethrough", + "code": 59464, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M968.8 562.5H31.3C14 562.5 0 548.5 0 531.3V468.8C0 451.5 14 437.5 31.3 437.5H968.8C986 437.5 1000 451.5 1000 468.8V531.3C1000 548.5 986 562.5 968.8 562.5ZM549.5 593.8C602.7 619 640.3 649.8 640.3 703.6 640.3 768.3 583.8 808.4 492.7 808.4 429.5 808.4 342.5 784.8 342.5 722V718.8C342.5 701.5 328.5 687.5 311.3 687.5H222.2C204.9 687.5 190.9 701.5 190.9 718.8V756.3C190.9 886.8 342.7 955.1 492.7 955.1 665.7 955.1 809.1 866.4 809.1 692.6 809.1 653.9 802 621.5 789.3 593.8H549.5ZM489 406.3C425.7 379.9 378 349.7 378 289.7 378 223.4 438.4 197.1 504.9 197.1 588.2 197.1 631.8 229.5 631.8 261.5V265.6C631.8 282.9 645.8 296.9 663 296.9H752.1C769.4 296.9 783.4 282.9 783.4 265.6V206.4C783.4 104 643.3 50.4 504.9 50.4 338.5 50.4 210.5 130.4 210.5 295.8 210.5 340.2 219.6 376.2 235.5 406.3H489Z", + "width": 1000 + }, + "search": [ + "strikethrough" + ] + }, + { + "uid": "1a1fa90cbaa7da526141f8be54d5491b", + "css": "indent", + "code": 59465, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M0 164.1V85.9C0 68.7 14 54.7 31.3 54.7H843.8C861 54.7 875 68.7 875 85.9V164.1C875 181.3 861 195.3 843.8 195.3H31.3C14 195.3 0 181.3 0 164.1ZM343.8 445.3H843.8C861 445.3 875 431.3 875 414.1V335.9C875 318.7 861 304.7 843.8 304.7H343.8C326.5 304.7 312.5 318.7 312.5 335.9V414.1C312.5 431.3 326.5 445.3 343.8 445.3ZM31.3 945.3H843.8C861 945.3 875 931.3 875 914.1V835.9C875 818.7 861 804.7 843.8 804.7H31.3C14 804.7 0 818.7 0 835.9V914.1C0 931.3 14 945.3 31.3 945.3ZM343.8 695.3H843.8C861 695.3 875 681.3 875 664.1V585.9C875 568.7 861 554.7 843.8 554.7H343.8C326.5 554.7 312.5 568.7 312.5 585.9V664.1C312.5 681.3 326.5 695.3 343.8 695.3ZM240.8 477.9L53.3 290.4C33.7 270.8 0 284.7 0 312.5V687.5C0 715.5 33.8 729.1 53.3 709.6L240.8 522.1C253.1 509.9 253.1 490.1 240.8 477.9Z", + "width": 875 + }, + "search": [ + "indent" + ] + }, + { + "uid": "8d1d056ea637f2f25e905cd5beac310e", + "css": "outdent", + "code": 59466, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M0 164.1V85.9C0 68.7 14 54.7 31.3 54.7H843.8C861 54.7 875 68.7 875 85.9V164.1C875 181.3 861 195.3 843.8 195.3H31.3C14 195.3 0 181.3 0 164.1ZM406.3 445.3H843.8C861 445.3 875 431.3 875 414.1V335.9C875 318.7 861 304.7 843.8 304.7H406.3C389 304.7 375 318.7 375 335.9V414.1C375 431.3 389 445.3 406.3 445.3ZM31.3 945.3H843.8C861 945.3 875 931.3 875 914.1V835.9C875 818.7 861 804.7 843.8 804.7H31.3C14 804.7 0 818.7 0 835.9V914.1C0 931.3 14 945.3 31.3 945.3ZM406.3 695.3H843.8C861 695.3 875 681.3 875 664.1V585.9C875 568.7 861 554.7 843.8 554.7H406.3C389 554.7 375 568.7 375 585.9V664.1C375 681.3 389 695.3 406.3 695.3ZM9.2 522.1L196.7 709.6C216.3 729.2 250 715.3 250 687.5V312.5C250 284.5 216.2 270.9 196.7 290.4L9.2 477.9C-3.1 490.1-3.1 509.9 9.2 522.1Z", + "width": 875 + }, + "search": [ + "outdent" + ] + }, + { + "uid": "097d911c1839d50e7183cfb6e7c16934", + "css": "undo-alt", + "code": 59467, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M499.1 15.6C369.7 15.9 252.2 66.9 165.4 149.8L95.6 80C66.1 50.5 15.6 71.4 15.6 113.2V375C15.6 400.9 36.6 421.9 62.5 421.9H324.3C366.1 421.9 387 371.4 357.5 341.9L275.9 260.3C336.2 203.9 414.2 172.6 497.1 171.9 677.6 170.3 829.7 316.4 828.1 502.8 826.6 679.7 683.2 828.1 500 828.1 419.7 828.1 343.8 799.5 283.9 747 274.7 738.8 260.7 739.3 252 748L174.5 825.5C165 835 165.4 850.5 175.4 859.6 261.3 937.1 375.1 984.4 500 984.4 767.5 984.4 984.4 767.5 984.4 500 984.4 232.8 766.3 15.1 499.1 15.6Z", + "width": 1000 + }, + "search": [ + "undo-alt" + ] + }, + { + "uid": "4bd031cc742bc0605f0d2a6c13eeb789", + "css": "redo-alt", + "code": 59468, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M500.9 15.6C630.3 15.9 747.8 66.9 834.6 149.8L904.4 80C933.9 50.5 984.4 71.4 984.4 113.2V375C984.4 400.9 963.4 421.9 937.5 421.9H675.7C633.9 421.9 613 371.4 642.5 341.9L724.1 260.3C663.8 203.9 585.8 172.6 502.9 171.9 322.4 170.3 170.3 316.4 171.9 502.8 173.4 679.7 316.8 828.1 500 828.1 580.3 828.1 656.2 799.5 716.1 747 725.3 738.8 739.3 739.3 748 748L825.5 825.5C835 835 834.6 850.5 824.6 859.6 738.7 937.1 624.9 984.4 500 984.4 232.5 984.4 15.6 767.5 15.6 500 15.6 232.8 233.7 15.1 500.9 15.6Z", + "width": 1000 + }, + "search": [ + "redo-alt" + ] + }, + { + "uid": "8a69d07fcdeb0deda9048dffdfeb03d3", + "css": "link", + "code": 59469, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M637.9 362.1C754.6 478.9 753 666.2 638.6 781.2 638.4 781.4 638.1 781.7 637.9 781.9L506.7 913.2C390.9 1028.9 202.6 1028.9 86.8 913.2-28.9 797.4-28.9 609.1 86.8 493.3L159.3 420.9C178.5 401.7 211.6 414.4 212.6 441.6 213.9 476.2 220.1 511 231.5 544.6 235.4 555.9 232.6 568.5 224.1 577L198.6 602.6C143.8 657.3 142.1 746.4 196.3 801.7 251.1 857.5 341 857.9 396.2 802.7L527.4 671.5C582.5 616.4 582.3 527.4 527.4 472.6 520.2 465.4 512.9 459.8 507.2 455.8A31.3 31.3 0 0 1 493.7 431.2C492.9 410.6 500.2 389.3 516.5 373L557.6 331.9C568.4 321.1 585.3 319.8 597.8 328.5A297.8 297.8 0 0 1 637.9 362.1ZM913.2 86.8C797.4-28.9 609.1-28.9 493.3 86.8L362.1 218.1C361.8 218.3 361.6 218.6 361.4 218.8 247 333.8 245.4 521.1 362.1 637.9A297.8 297.8 0 0 0 402.2 671.5C414.7 680.2 431.6 678.9 442.4 668.1L483.5 627C499.8 610.7 507.1 589.4 506.3 568.8A31.3 31.3 0 0 0 492.8 544.2C487.1 540.2 479.8 534.6 472.6 527.4 417.7 472.6 417.5 383.6 472.6 328.5L603.8 197.3C659 142.1 748.9 142.5 803.7 198.3 857.9 253.6 856.2 342.7 801.4 397.4L775.9 423C767.4 431.5 764.6 444.1 768.5 455.4 779.9 489 786.1 523.8 787.4 558.4 788.4 585.6 821.5 598.3 840.7 579.1L913.2 506.7C1028.9 390.9 1028.9 202.6 913.2 86.8Z", + "width": 1000 + }, + "search": [ + "link" + ] + }, + { + "uid": "195e10d964b70c44cde9513ec217cba4", + "css": "font", + "code": 59470, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M843.8 812.5H791.6L538.1 83.4C533.8 70.9 521.9 62.5 508.6 62.5H366.4C353.1 62.5 341.2 70.9 336.9 83.4L83.4 812.5H31.3C14.1 812.5 0 826.6 0 843.8V906.3C0 923.4 14.1 937.5 31.3 937.5H296.9C314.1 937.5 328.1 923.4 328.1 906.3V843.8C328.1 826.6 314.1 812.5 296.9 812.5H250L302 654.7H571.9L623.8 812.5H578.1C560.9 812.5 546.9 826.6 546.9 843.8V906.3C546.9 923.4 560.9 937.5 578.1 937.5H843.8C860.9 937.5 875 923.4 875 906.3V843.8C875 826.6 860.9 812.5 843.8 812.5ZM340.6 524L422.7 281.6C431.1 252 435.5 226.6 437.5 214.1 439.1 226.8 443.2 252.1 452.5 281.8L533.2 524Z", + "width": 875 + }, + "search": [ + "font" + ] + }, + { + "uid": "e9352fe9c753373d14694398ce8044fe", + "css": "comment-medical", + "code": 59471, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M500 62.5C223.9 62.5 0 244.4 0 468.8 0 565.5 41.8 654.3 111.3 724.1 86.8 822.4 5.3 910.2 4.3 911.1A15.6 15.6 0 0 0 15.6 937.5C145 937.5 242.2 875.5 290.2 837.1A595 595 0 0 0 500 875C776.2 875 1000 693.1 1000 468.8S776.2 62.5 500 62.5ZM687.5 515.6A15.6 15.6 0 0 1 671.9 531.3H562.5V640.6A15.6 15.6 0 0 1 546.9 656.3H453.1A15.6 15.6 0 0 1 437.5 640.6V531.3H328.1A15.6 15.6 0 0 1 312.5 515.6V421.9A15.6 15.6 0 0 1 328.1 406.3H437.5V296.9A15.6 15.6 0 0 1 453.1 281.3H546.9A15.6 15.6 0 0 1 562.5 296.9V406.3H671.9A15.6 15.6 0 0 1 687.5 421.9Z", + "width": 1000 + }, + "search": [ + "comment-medical" + ] + }, + { + "uid": "a5c7ef2089dd63c12d3328563fee2330", + "css": "comment", + "code": 59472, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M500 62.5C223.8 62.5 0 244.3 0 468.8 0 565.6 41.8 654.3 111.3 724 86.9 822.5 5.3 910.2 4.3 911.1 0 915.6-1.2 922.3 1.4 928.1S9.4 937.5 15.6 937.5C145.1 937.5 242.2 875.4 290.2 837.1 354.1 861.1 425 875 500 875 776.2 875 1000 693.2 1000 468.8S776.2 62.5 500 62.5Z", + "width": 1000 + }, + "search": [ + "comment" + ] + }, + { + "uid": "5455d3369b90673f0404f9290f40f074", + "css": "cog", + "code": 59473, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M952 616.6L868.7 568.6C877.1 523.2 877.1 476.8 868.7 431.4L952 383.4C961.5 377.9 965.8 366.6 962.7 356.1 941 286.5 904.1 223.6 855.9 171.3 848.4 163.3 836.3 161.3 827 166.8L743.8 214.8C708.8 184.8 668.6 161.5 625 146.3V50.4C625 39.5 617.4 29.9 606.6 27.5 535 11.5 461.5 12.3 393.4 27.5 382.6 29.9 375 39.5 375 50.4V146.5C331.6 161.9 291.4 185.2 256.3 215L173.2 167C163.7 161.5 151.8 163.3 144.3 171.5 96.1 223.6 59.2 286.5 37.5 356.2 34.2 366.8 38.7 378.1 48.2 383.6L131.4 431.6C123 477 123 523.4 131.4 568.8L48.2 616.8C38.7 622.3 34.4 633.6 37.5 644.1 59.2 713.7 96.1 776.6 144.3 828.9 151.8 836.9 163.9 838.9 173.2 833.4L256.4 785.4C291.4 815.4 331.6 838.7 375.2 853.9V950C375.2 960.9 382.8 970.5 393.6 972.9 465.2 988.9 538.7 988.1 606.8 972.9 617.6 970.5 625.2 960.9 625.2 950V853.9C668.6 838.5 708.8 815.2 743.9 785.4L827.1 833.4C836.7 838.9 848.6 837.1 856.1 828.9 904.3 776.8 941.2 713.9 962.9 644.1 965.8 633.4 961.5 622.1 952 616.6ZM500 656.3C413.9 656.3 343.8 586.1 343.8 500S413.9 343.8 500 343.8 656.3 413.9 656.3 500 586.1 656.3 500 656.3Z", + "width": 1000 + }, + "search": [ + "cog" + ] + }, + { + "uid": "320da42dd92a9773159f2e4037a1d1db", + "css": "text-height", + "code": 59474, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M31.3 62.5H593.8C611 62.5 625 76.5 625 93.8V281.3C625 298.5 611 312.5 593.8 312.5H524.4C507.2 312.5 493.2 298.5 493.2 281.3V187.5H386.2V812.5H453.1C470.4 812.5 484.4 826.5 484.4 843.8V906.3C484.4 923.5 470.4 937.5 453.1 937.5H171.9C154.6 937.5 140.6 923.5 140.6 906.3V843.8C140.6 826.5 154.6 812.5 171.9 812.5H238.8V187.5H131.8V281.3C131.8 298.5 117.8 312.5 100.6 312.5H31.3C14 312.5 0 298.5 0 281.3V93.8C0 76.5 14 62.5 31.3 62.5ZM959.6 71.7L1115.8 227.9C1135.4 247.4 1121.7 281.3 1093.7 281.3H1000V718.8H1093.8C1124.3 718.8 1134.1 753.9 1115.8 772.1L959.6 928.3C947.4 940.6 927.6 940.5 915.4 928.3L759.2 772.1C739.6 752.6 753.3 718.8 781.3 718.8H875V281.3H781.3C750.7 281.3 740.9 246.1 759.2 227.9L915.4 71.7C927.6 59.4 947.4 59.5 959.6 71.7Z", + "width": 1125 + }, + "search": [ + "text-height" + ] + }, + { + "uid": "bc0f1614c05e71b1c8beaf95bc900761", + "css": "share-alt", + "code": 59475, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M687.5 625C643.3 625 602.8 640.3 570.7 665.8L370.6 540.7A188.6 188.6 0 0 0 370.6 459.3L570.7 334.2C602.8 359.7 643.3 375 687.5 375 791.1 375 875 291.1 875 187.5S791.1 0 687.5 0 500 83.9 500 187.5C500 201.5 501.5 215.1 504.4 228.2L304.3 353.3C272.2 327.8 231.7 312.5 187.5 312.5 83.9 312.5 0 396.4 0 500S83.9 687.5 187.5 687.5C231.7 687.5 272.2 672.2 304.3 646.7L504.4 771.8A188.1 188.1 0 0 0 500 812.5C500 916.1 583.9 1000 687.5 1000S875 916.1 875 812.5 791.1 625 687.5 625Z", + "width": 875 + }, + "search": [ + "share-alt" + ] + }, + { + "uid": "ef49eade5ad70fcd1daa78d8d16bd68b", + "css": "code", + "code": 59476, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M544.7 999L425.6 964.5C413.1 960.9 406.1 947.9 409.6 935.4L676.2 17C679.7 4.5 692.8-2.5 705.3 1L824.4 35.5C836.9 39.1 843.9 52.1 840.4 64.6L573.8 983C570.1 995.5 557.2 1002.7 544.7 999ZM322.1 779.9L407 689.3C416 679.7 415.4 664.5 405.5 655.7L228.5 500 405.5 344.3C415.4 335.5 416.2 320.3 407 310.7L322.1 220.1C313.3 210.7 298.4 210.2 288.9 219.1L7.4 482.8C-2.5 492-2.5 507.8 7.4 517L288.9 780.9C298.4 789.8 313.3 789.5 322.1 779.9ZM961.1 781.1L1242.6 517.2C1252.5 508 1252.5 492.2 1242.6 483L961.1 218.9C951.8 210.2 936.9 210.5 927.9 219.9L843 310.5C834 320.1 834.6 335.4 844.5 344.1L1021.5 500 844.5 655.7C834.6 664.5 833.8 679.7 843 689.3L927.9 779.9C936.7 789.5 951.6 789.8 961.1 781.1Z", + "width": 1250 + }, + "search": [ + "code" + ] + }, + { + "uid": "b3fb5fc84c956ceabfd7ec42ee3fc5dd", + "css": "history", + "code": 59477, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M984.4 499.1C984.9 766 767.2 984.2 500.4 984.4 385.1 984.5 279.2 944.3 196 877.1 174.4 859.7 172.8 827.2 192.4 807.6L214.4 785.6C231.2 768.8 258.1 766.9 276.7 781.7 338 830.3 415.6 859.4 500 859.4 698.6 859.4 859.4 698.6 859.4 500 859.4 301.4 698.6 140.6 500 140.6 404.7 140.6 318.1 177.7 253.8 238.1L352.9 337.3C372.6 357 358.6 390.6 330.8 390.6H46.9C29.6 390.6 15.6 376.6 15.6 359.4V75.4C15.6 47.6 49.3 33.7 69 53.3L165.4 149.8C252.4 66.7 370.2 15.6 500 15.6 767.2 15.6 983.9 232 984.4 499.1ZM631 653L650.2 628.3C666.1 607.9 662.4 578.4 642 562.5L562.5 500.7V296.9C562.5 271 541.5 250 515.6 250H484.4C458.5 250 437.5 271 437.5 296.9V561.8L565.3 661.2C585.7 677.1 615.1 673.4 631 653Z", + "width": 1000 + }, + "search": [ + "history" + ] + }, + { + "uid": "bed311f2f0699a3e55a635284d86a5c7", + "css": "star", + "code": 59478, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M506.4 34.8L378.9 293.4 93.6 335C42.4 342.4 21.9 405.5 59 441.6L265.4 642.8 216.6 927C207.8 978.3 261.9 1016.8 307.2 992.8L562.5 858.6 817.8 992.8C863.1 1016.6 917.2 978.3 908.4 927L859.6 642.8 1066 441.6C1103.1 405.5 1082.6 342.4 1031.4 335L746.1 293.4 618.6 34.8C595.7-11.3 529.5-11.9 506.4 34.8Z", + "width": 1125 + }, + "search": [ + "star" + ] + }, + { + "uid": "28feb41c0766d59e9f56b2c4c9cb67a5", + "css": "file-import", + "code": 59479, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M31.3 562.5C14.1 562.5 0 576.6 0 593.8V656.3C0 673.4 14.1 687.5 31.3 687.5H250V562.5ZM986.3 205.1L795.1 13.7C786.3 4.9 774.4 0 761.9 0H750V250H1000V238.1C1000 225.8 995.1 213.9 986.3 205.1ZM687.5 265.6V0H296.9C270.9 0 250 20.9 250 46.9V562.5H500V435.2C500 407.2 533.8 393.4 553.5 413.1L740.2 601.6C753.1 614.6 753.1 635.5 740.2 648.4L553.3 836.7C533.6 856.4 499.8 842.6 499.8 814.6V687.5H250V953.1C250 979.1 270.9 1000 296.9 1000H953.1C979.1 1000 1000 979.1 1000 953.1V312.5H734.4C708.6 312.5 687.5 291.4 687.5 265.6Z", + "width": 1000 + }, + "search": [ + "file-import" + ] + }, + { + "uid": "a4382bef7f9361b8dacb8ae0b42691a4", + "css": "file-download", + "code": 59480, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M437.5 265.6V0H46.9C20.9 0 0 20.9 0 46.9V953.1C0 979.1 20.9 1000 46.9 1000H703.1C729.1 1000 750 979.1 750 953.1V312.5H484.4C458.6 312.5 437.5 291.4 437.5 265.6ZM586.8 678.4L398.5 865.4C385.5 878.3 364.5 878.3 351.5 865.4L163.2 678.4C143.4 658.8 157.3 625 185.2 625H312.5V468.8C312.5 451.5 326.5 437.5 343.8 437.5H406.3C423.5 437.5 437.5 451.5 437.5 468.8V625H564.8C592.7 625 606.6 658.8 586.8 678.4ZM736.3 205.1L545.1 13.7C536.3 4.9 524.4 0 511.9 0H500V250H750V238.1C750 225.8 745.1 213.9 736.3 205.1Z", + "width": 750 + }, + "search": [ + "file-download" + ] + }, + { + "uid": "149eec703c4bd1d93f052f3d239cce44", + "css": "file-pdf", + "code": 59481, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M355.3 500.2C345.5 468.9 345.7 408.6 351.4 408.6 367.8 408.6 366.2 480.7 355.3 500.2ZM352 592.4C336.9 631.8 318.2 677 296.5 714.8 332.2 701.2 372.7 681.3 419.3 672.1 394.5 653.3 370.7 626.4 352 592.4ZM168.2 836.1C168.2 837.7 193.9 825.6 236.3 757.6 223.2 769.9 179.5 805.5 168.2 836.1ZM484.4 312.5H750V953.1C750 979.1 729.1 1000 703.1 1000H46.9C20.9 1000 0 979.1 0 953.1V46.9C0 20.9 20.9 0 46.9 0H437.5V265.6C437.5 291.4 458.6 312.5 484.4 312.5ZM468.8 648C429.7 624.2 403.7 591.4 385.4 543 394.1 506.8 408 452 397.5 417.6 388.3 360.2 314.6 365.8 304.1 404.3 294.3 440 303.3 490.4 319.9 554.7 297.3 608.6 263.9 680.9 240.2 722.3 240 722.3 240 722.5 239.8 722.5 186.9 749.6 96.1 809.4 133.4 855.3 144.3 868.8 164.6 874.8 175.4 874.8 210.4 874.8 245.1 839.6 294.7 754.1 345.1 737.5 400.4 716.8 449 708.8 491.4 731.8 541 746.9 574 746.9 631.1 746.9 635 684.4 612.5 662.1 585.4 635.5 506.4 643.2 468.7 648ZM736.3 205.1L544.9 13.7C536.1 4.9 524.2 0 511.7 0H500V250H750V238.1C750 225.8 745.1 213.9 736.3 205.1ZM591.6 703.7C599.6 698.4 586.7 680.5 508 686.1 580.5 717 591.6 703.7 591.6 703.7Z", + "width": 750 + }, + "search": [ + "file-pdf" + ] + }, + { + "uid": "43c33879f17fb9c62a7466659a1a9347", + "css": "file-word", + "code": 59482, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M437.5 265.6V0H46.9C20.9 0 0 20.9 0 46.9V953.1C0 979.1 20.9 1000 46.9 1000H703.1C729.1 1000 750 979.1 750 953.1V312.5H484.4C458.6 312.5 437.5 291.4 437.5 265.6ZM549 500H595.7C610.7 500 621.9 513.9 618.6 528.7L544.3 856.8C542 867.6 532.4 875 521.5 875H447.3C436.5 875 427.1 867.6 424.6 857.2 374.2 655.1 384 698.6 374.6 641.4H373.6C371.5 669.3 368.9 675.4 323.6 857.2 321.1 867.6 311.7 875 301 875H228.5C217.6 875 208 867.4 205.7 856.6L131.8 528.5C128.5 513.9 139.6 500 154.7 500H202.5C213.7 500 223.4 507.8 225.6 518.9 256.1 671.3 264.8 732.8 266.6 757.6 269.7 737.7 280.9 693.8 324 518 326.6 507.4 335.9 500.2 346.9 500.2H403.7C414.6 500.2 424 507.6 426.6 518.2 473.4 714.3 482.8 760.4 484.4 770.9 484 749 479.3 736.1 526.6 518.6 528.5 507.6 538.1 500 549 500ZM750 238.1V250H500V0H511.9C524.4 0 536.3 4.9 545.1 13.7L736.3 205.1C745.1 213.9 750 225.8 750 238.1Z", + "width": 750 + }, + "search": [ + "file-word" + ] + }, + { + "uid": "5d3cbbf4f54f53889ff77614613a050d", + "css": "file-alt", + "code": 59483, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M437.5 265.6V0H46.9C20.9 0 0 20.9 0 46.9V953.1C0 979.1 20.9 1000 46.9 1000H703.1C729.1 1000 750 979.1 750 953.1V312.5H484.4C458.6 312.5 437.5 291.4 437.5 265.6ZM562.5 726.6C562.5 739.5 552 750 539.1 750H210.9C198 750 187.5 739.5 187.5 726.6V710.9C187.5 698 198 687.5 210.9 687.5H539.1C552 687.5 562.5 698 562.5 710.9V726.6ZM562.5 601.6C562.5 614.5 552 625 539.1 625H210.9C198 625 187.5 614.5 187.5 601.6V585.9C187.5 573 198 562.5 210.9 562.5H539.1C552 562.5 562.5 573 562.5 585.9V601.6ZM562.5 460.9V476.6C562.5 489.5 552 500 539.1 500H210.9C198 500 187.5 489.5 187.5 476.6V460.9C187.5 448 198 437.5 210.9 437.5H539.1C552 437.5 562.5 448 562.5 460.9ZM750 238.1V250H500V0H511.9C524.4 0 536.3 4.9 545.1 13.7L736.3 205.1C745.1 213.9 750 225.8 750 238.1Z", + "width": 750 + }, + "search": [ + "file-alt" + ] + }, + { + "uid": "c718261461d9a8046891e6c68d610118", + "css": "file", + "code": 59484, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M437.5 265.6V0H46.9C20.9 0 0 20.9 0 46.9V953.1C0 979.1 20.9 1000 46.9 1000H703.1C729.1 1000 750 979.1 750 953.1V312.5H484.4C458.6 312.5 437.5 291.4 437.5 265.6ZM750 238.1V250H500V0H511.9C524.4 0 536.3 4.9 545.1 13.7L736.3 205.1C745.1 213.9 750 225.8 750 238.1Z", + "width": 750 + }, + "search": [ + "file" + ] + }, + { + "uid": "9a14f9bdf73d4f035ecb964e16f27b5b", + "css": "users", + "code": 59445, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M187.5 437.5C256.4 437.5 312.5 381.4 312.5 312.5S256.4 187.5 187.5 187.5 62.5 243.6 62.5 312.5 118.6 437.5 187.5 437.5ZM1062.5 437.5C1131.4 437.5 1187.5 381.4 1187.5 312.5S1131.4 187.5 1062.5 187.5 937.5 243.6 937.5 312.5 993.6 437.5 1062.5 437.5ZM1125 500H1000C965.6 500 934.6 513.9 911.9 536.3 990.6 579.5 1046.5 657.4 1058.6 750H1187.5C1222.1 750 1250 722.1 1250 687.5V625C1250 556.1 1193.9 500 1125 500ZM625 500C745.9 500 843.8 402.1 843.8 281.3S745.9 62.5 625 62.5 406.3 160.4 406.3 281.3 504.1 500 625 500ZM775 562.5H758.8C718.2 582 673 593.8 625 593.8S532 582 491.2 562.5H475C350.8 562.5 250 663.3 250 787.5V843.8C250 895.5 292 937.5 343.8 937.5H906.3C958 937.5 1000 895.5 1000 843.8V787.5C1000 663.3 899.2 562.5 775 562.5ZM338.1 536.3C315.4 513.9 284.4 500 250 500H125C56.1 500 0 556.1 0 625V687.5C0 722.1 27.9 750 62.5 750H191.2C203.5 657.4 259.4 579.5 338.1 536.3Z", + "width": 1250 + }, + "search": [ + "users" + ] + }, + { + "uid": "5ce9d7d62b842d1e0b42ccb50417ed86", + "css": "pencil-alt", + "code": 59400, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M972.5 277.5L882.4 367.6C873.2 376.8 858.4 376.8 849.2 367.6L632.4 150.8C623.2 141.6 623.2 126.8 632.4 117.6L722.5 27.5C759-9 818.4-9 855.1 27.5L972.5 144.9C1009.2 181.4 1009.2 240.8 972.5 277.5ZM555.1 194.9L42.2 707.8 0.8 945.1C-4.9 977.1 23 1004.9 55.1 999.4L292.4 957.8 805.3 444.9C814.5 435.7 814.5 420.9 805.3 411.7L588.5 194.9C579.1 185.7 564.3 185.7 555.1 194.9ZM242.4 663.9C231.6 653.1 231.6 635.9 242.4 625.2L543.2 324.4C553.9 313.7 571.1 313.7 581.8 324.4S592.6 352.3 581.8 363.1L281.1 663.9C270.3 674.6 253.1 674.6 242.4 663.9ZM171.9 828.1H265.6V899L139.6 921.1 78.9 860.4 101 734.4H171.9V828.1Z", + "width": 1000 + }, + "search": [ + "pencil-alt" + ] + }, + { + "uid": "88a8e61cd1555895e8af136db8b58885", + "css": "times", + "code": 59430, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M474.1 500L669.5 304.6C693.5 280.6 693.5 241.7 669.5 217.7L626.1 174.2C602.1 150.3 563.2 150.3 539.2 174.2L343.8 369.7 148.3 174.2C124.3 150.3 85.4 150.3 61.4 174.2L18 217.7C-6 241.7-6 280.5 18 304.6L213.4 500 18 695.4C-6 719.4-6 758.3 18 782.3L61.4 825.8C85.4 849.7 124.3 849.7 148.3 825.8L343.8 630.3 539.2 825.8C563.2 849.7 602.1 849.7 626.1 825.8L669.5 782.3C693.5 758.3 693.5 719.5 669.5 695.4L474.1 500Z", + "width": 688 + }, + "search": [ + "times" + ] + }, + { + "uid": "91c50bb767ec3d33047773a7e539799e", + "css": "pause", + "code": 59433, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M281.3 935.5H93.8C42 935.5 0 893.6 0 841.8V154.3C0 102.5 42 60.5 93.8 60.5H281.3C333 60.5 375 102.5 375 154.3V841.8C375 893.6 333 935.5 281.3 935.5ZM875 841.8V154.3C875 102.5 833 60.5 781.3 60.5H593.8C542 60.5 500 102.5 500 154.3V841.8C500 893.6 542 935.5 593.8 935.5H781.3C833 935.5 875 893.6 875 841.8Z", + "width": 875 + }, + "search": [ + "pause" + ] + }, + { + "uid": "3053a00ac47ec0a6e52490d34a2251eb", + "css": "stop", + "code": 59394, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M781.3 62.5H93.8C42 62.5 0 104.5 0 156.3V843.8C0 895.5 42 937.5 93.8 937.5H781.3C833 937.5 875 895.5 875 843.8V156.3C875 104.5 833 62.5 781.3 62.5Z", + "width": 875 + }, + "search": [ + "stop" + ] + }, + { + "uid": "91b4828047e0874d4b2cfbb44dc16ff9", + "css": "step-backward", + "code": 59435, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M125 914.1V85.9C125 73 135.5 62.5 148.4 62.5H242.2C255.1 62.5 265.6 73 265.6 85.9V430.5L647.5 77C687.7 43.6 750 71.5 750 125V875C750 928.5 687.7 956.4 647.5 923L265.6 571.7V914.1C265.6 927 255.1 937.5 242.2 937.5H148.4C135.5 937.5 125 927 125 914.1Z", + "width": 875 + }, + "search": [ + "step-backward" + ] + }, + { + "uid": "9a0d3eec2bb3765a51f82dadf9a10bd1", + "css": "step-forward", + "code": 59436, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M750 85.9V914.1C750 927 739.5 937.5 726.6 937.5H632.8C619.9 937.5 609.4 927 609.4 914.1V569.5L227.5 923C187.3 956.4 125 928.5 125 875V125C125 71.5 187.3 43.6 227.5 77L609.4 428.3V85.9C609.4 73 619.9 62.5 632.8 62.5H726.6C739.5 62.5 750 73 750 85.9Z", + "width": 875 + }, + "search": [ + "step-forward" + ] + }, + { + "uid": "9f8f8db47c9da55d8ea2e0170476eb39", + "css": "play", + "code": 59395, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M828.9 419.3L141.4 12.9C85.5-20.1 0 11.9 0 93.6V906.3C0 979.5 79.5 1023.6 141.4 986.9L828.9 580.7C890.2 544.5 890.4 455.5 828.9 419.3Z", + "width": 875 + }, + "search": [ + "play" + ] + }, + { + "uid": "e0e61c06ec2c00a0c7b604fcc20b133c", + "css": "comments", + "code": 59437, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M812.5 375C812.5 202.3 630.7 62.5 406.3 62.5S0 202.3 0 375C0 442 27.5 503.7 74.2 554.7 48 613.7 4.9 660.5 4.3 661.1 0 665.6-1.2 672.3 1.4 678.1S9.4 687.5 15.6 687.5C87.1 687.5 146.3 663.5 188.9 638.7 251.8 669.3 326.2 687.5 406.3 687.5 630.7 687.5 812.5 547.7 812.5 375ZM1050.8 804.7C1097.5 753.9 1125 692 1125 625 1125 494.3 1020.5 382.4 872.5 335.7 874.2 348.6 875 361.7 875 375 875 581.8 664.6 750 406.3 750 385.2 750 364.6 748.4 344.3 746.3 405.9 858.6 550.4 937.5 718.8 937.5 798.8 937.5 873.2 919.5 936.1 888.7 978.7 913.5 1037.9 937.5 1109.4 937.5 1115.6 937.5 1121.3 933.8 1123.6 928.1 1126.2 922.5 1125 915.8 1120.7 911.1 1120.1 910.5 1077 863.9 1050.8 804.7Z", + "width": 1125 + }, + "search": [ + "comments" + ] + }, + { + "uid": "7c8b7bccd2548457f00645f3954e2863", + "css": "heading", + "code": 59438, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M968.8 156.3V93.8C968.8 76.5 954.8 62.5 937.5 62.5H625C607.7 62.5 593.8 76.5 593.8 93.8V156.3C593.8 173.5 607.7 187.5 625 187.5H698.5V437.5H301.5V187.5H375C392.3 187.5 406.3 173.5 406.3 156.3V93.8C406.3 76.5 392.3 62.5 375 62.5H62.5C45.2 62.5 31.3 76.5 31.3 93.8V156.3C31.3 173.5 45.2 187.5 62.5 187.5H135.3V812.5H62.5C45.2 812.5 31.3 826.5 31.3 843.8V906.3C31.3 923.5 45.2 937.5 62.5 937.5H375C392.3 937.5 406.3 923.5 406.3 906.3V843.8C406.3 826.5 392.3 812.5 375 812.5H301.5V562.5H698.5V812.5H625C607.7 812.5 593.8 826.5 593.8 843.8V906.3C593.8 923.5 607.7 937.5 625 937.5H937.5C954.8 937.5 968.8 923.5 968.8 906.3V843.8C968.8 826.5 954.8 812.5 937.5 812.5H864.7V187.5H937.5C954.8 187.5 968.8 173.5 968.8 156.3Z", + "width": 1000 + }, + "search": [ + "heading" + ] + }, + { + "uid": "c7ead3a5bb66fddf32a7899a0f3fbb6c", + "css": "align-center", + "code": 59396, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M687.5 85.9V164.1C687.5 181.3 673.5 195.3 656.3 195.3H218.8C201.5 195.3 187.5 181.3 187.5 164.1V85.9C187.5 68.7 201.5 54.7 218.8 54.7H656.3C673.5 54.7 687.5 68.7 687.5 85.9ZM31.3 445.3H843.8C861 445.3 875 431.3 875 414.1V335.9C875 318.7 861 304.7 843.8 304.7H31.3C14 304.7 0 318.7 0 335.9V414.1C0 431.3 14 445.3 31.3 445.3ZM31.3 945.3H843.8C861 945.3 875 931.3 875 914.1V835.9C875 818.7 861 804.7 843.8 804.7H31.3C14 804.7 0 818.7 0 835.9V914.1C0 931.3 14 945.3 31.3 945.3ZM656.3 554.7H218.8C201.5 554.7 187.5 568.7 187.5 585.9V664.1C187.5 681.3 201.5 695.3 218.8 695.3H656.3C673.5 695.3 687.5 681.3 687.5 664.1V585.9C687.5 568.7 673.5 554.7 656.3 554.7Z", + "width": 875 + }, + "search": [ + "align-center" + ] + }, + { + "uid": "e8e401b7ba1649fce89eb32cc85cb50d", + "css": "align-justify", + "code": 59397, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M0 164.1V85.9C0 68.7 14 54.7 31.3 54.7H843.8C861 54.7 875 68.7 875 85.9V164.1C875 181.3 861 195.3 843.8 195.3H31.3C14 195.3 0 181.3 0 164.1ZM31.3 445.3H843.8C861 445.3 875 431.3 875 414.1V335.9C875 318.7 861 304.7 843.8 304.7H31.3C14 304.7 0 318.7 0 335.9V414.1C0 431.3 14 445.3 31.3 445.3ZM31.3 945.3H843.8C861 945.3 875 931.3 875 914.1V835.9C875 818.7 861 804.7 843.8 804.7H31.3C14 804.7 0 818.7 0 835.9V914.1C0 931.3 14 945.3 31.3 945.3ZM31.3 695.3H843.8C861 695.3 875 681.3 875 664.1V585.9C875 568.7 861 554.7 843.8 554.7H31.3C14 554.7 0 568.7 0 585.9V664.1C0 681.3 14 695.3 31.3 695.3Z", + "width": 875 + }, + "search": [ + "align-justify" + ] + }, + { + "uid": "eb15f17c97d08c4151e60b4b2f630fb5", + "css": "align-left", + "code": 59398, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M562.5 85.9V164.1C562.5 181.3 548.5 195.3 531.3 195.3H31.3C14 195.3 0 181.3 0 164.1V85.9C0 68.7 14 54.7 31.3 54.7H531.3C548.5 54.7 562.5 68.7 562.5 85.9ZM0 335.9V414.1C0 431.3 14 445.3 31.3 445.3H843.8C861 445.3 875 431.3 875 414.1V335.9C875 318.7 861 304.7 843.8 304.7H31.3C14 304.7 0 318.7 0 335.9ZM31.3 945.3H843.8C861 945.3 875 931.3 875 914.1V835.9C875 818.7 861 804.7 843.8 804.7H31.3C14 804.7 0 818.7 0 835.9V914.1C0 931.3 14 945.3 31.3 945.3ZM531.3 554.7H31.3C14 554.7 0 568.7 0 585.9V664.1C0 681.3 14 695.3 31.3 695.3H531.3C548.5 695.3 562.5 681.3 562.5 664.1V585.9C562.5 568.7 548.5 554.7 531.3 554.7Z", + "width": 875 + }, + "search": [ + "align-left" + ] + }, + { + "uid": "48f22afc96cf17626d8da876b9b463dc", + "css": "align-right", + "code": 59399, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M312.5 164.1V85.9C312.5 68.7 326.5 54.7 343.8 54.7H843.8C861 54.7 875 68.7 875 85.9V164.1C875 181.3 861 195.3 843.8 195.3H343.8C326.5 195.3 312.5 181.3 312.5 164.1ZM31.3 445.3H843.8C861 445.3 875 431.3 875 414.1V335.9C875 318.7 861 304.7 843.8 304.7H31.3C14 304.7 0 318.7 0 335.9V414.1C0 431.3 14 445.3 31.3 445.3ZM31.3 945.3H843.8C861 945.3 875 931.3 875 914.1V835.9C875 818.7 861 804.7 843.8 804.7H31.3C14 804.7 0 818.7 0 835.9V914.1C0 931.3 14 945.3 31.3 945.3ZM343.8 695.3H843.8C861 695.3 875 681.3 875 664.1V585.9C875 568.7 861 554.7 843.8 554.7H343.8C326.5 554.7 312.5 568.7 312.5 585.9V664.1C312.5 681.3 326.5 695.3 343.8 695.3Z", + "width": 875 + }, + "search": [ + "align-right" + ] + }, + { + "uid": "b2d03fd882d7c96479a3c6c1dbc1a889", + "css": "file-powerpoint", + "code": 59485, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M378.3 529.7C395.5 529.7 408.6 535 418 545.5 436.7 566.8 437.1 609.4 417.6 631.6 408 642.6 394.3 648.2 376.4 648.2H323.8V529.7H378.3ZM736.3 205.1L544.9 13.7C536.1 4.9 524.2 0 511.7 0H500V250H750V238.1C750 225.8 745.1 213.9 736.3 205.1ZM437.5 265.6V0H46.9C20.9 0 0 20.9 0 46.9V953.1C0 979.1 20.9 1000 46.9 1000H703.1C729.1 1000 750 979.1 750 953.1V312.5H484.4C458.6 312.5 437.5 291.4 437.5 265.6ZM541 588.3C541 764.6 367.6 739.8 324 739.8V851.6C324 864.5 313.5 875 300.6 875H240.4C227.5 875 217 864.5 217 851.6V461.3C217 448.4 227.5 437.9 240.4 437.9H398.6C485.5 437.9 541 502 541 588.3Z", + "width": 750 + }, + "search": [ + "file-powerpoint" + ] + }, + { + "uid": "c59ea6604f4c8a3bebd9cb24630f0e3b", + "css": "superscript", + "code": 59443, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M531.3 375H398.8C388.1 375 377.9 380.7 372.3 389.8L293.6 516.8C289.1 523.8 284.8 531.1 281.4 537.3 278.1 531.1 274.2 524 270.3 517L192.4 389.8C186.7 380.7 176.6 375 165.8 375H31.3C14.1 375 0 389.1 0 406.3V468.8C0 485.9 14.1 500 31.3 500H90L193.2 651 82.6 812.5H31.3C14.1 812.5 0 826.6 0 843.8V906.3C0 923.4 14.1 937.5 31.3 937.5H156.3C167 937.5 177.1 931.8 182.8 922.7L270.1 781.8C274.4 774.8 278.3 767.6 281.6 761.1 285.2 767.4 289.3 774.6 293.8 781.1L383 922.9C388.7 932 398.6 937.5 409.4 937.5H531.3C548.4 937.5 562.5 923.4 562.5 906.2V843.7C562.5 826.6 548.4 812.5 531.3 812.5H488.3L373.8 647.9 476.6 500H531.3C548.4 500 562.5 485.9 562.5 468.8V406.3C562.5 389.1 548.4 375 531.3 375ZM968.8 500H771.9C778.7 479.5 808.6 458.4 842.8 436.7 875.2 416 912.1 392.6 941 360.7 975.2 323.4 991.6 282.2 991.6 234.6 991.6 116.2 892.6 62.5 800.6 62.5 717.6 62.5 651.4 105.5 616.2 160.9 607 175.2 611.1 194.1 625.2 203.7L684.4 243.4C698 252.5 716.6 249.4 726.6 236.3 742.2 216 763.3 200.8 788.5 200.8 826.4 200.8 839.8 226 839.8 247.5 839.8 318.2 606.6 358.8 606.6 560 606.6 573 607.8 585.4 609.4 597.7 611.5 613.3 624.6 624.8 640.4 624.8H968.8C985.9 624.8 1000 610.7 1000 593.6V531.1C1000 514.1 985.9 500 968.8 500Z", + "width": 1000 + }, + "search": [ + "superscript" + ] + }, + { + "uid": "cb9e27f4e2c9fe6182e2351f9ad71c14", + "css": "subscript", + "code": 59444, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M531.3 62.5H398.8C388.1 62.5 377.9 68.2 372.3 77.3L293.6 204.3C289.1 211.3 284.8 218.6 281.4 224.8 278.1 218.6 274.2 211.5 270.3 204.5L192.4 77.3C186.7 68.2 176.6 62.5 165.8 62.5H31.3C14.1 62.5 0 76.6 0 93.8V156.3C0 173.4 14.1 187.5 31.3 187.5H90L193.2 338.5 82.6 500H31.3C14.1 500 0 514.1 0 531.3V593.8C0 610.9 14.1 625 31.3 625H156.3C167 625 177.1 619.3 182.8 610.2L270.1 469.3C274.4 462.3 278.3 455.1 281.6 448.6 285.2 454.9 289.3 462.1 293.8 468.6L383 610.4C388.7 619.5 398.6 625 409.4 625H531.3C548.4 625 562.5 610.9 562.5 593.8V531.3C562.5 514.1 548.4 500 531.3 500H488.3L373.8 335.4 476.6 187.5H531.3C548.4 187.5 562.5 173.4 562.5 156.3V93.8C562.5 76.6 548.4 62.5 531.3 62.5ZM968.8 812.5H771.9C778.7 792 808.6 770.9 842.8 749.2 875.2 728.5 912.1 705.1 941 673.2 975.2 635.9 991.6 594.7 991.6 547.1 991.6 428.7 892.6 375 800.6 375 717.6 375 651.4 418 616.2 473.4 607 487.7 611.1 506.6 625.2 516.2L684.4 555.9C698 565 716.6 561.9 726.6 548.8 742.2 528.5 763.3 513.3 788.5 513.3 826.4 513.3 839.8 538.5 839.8 560 839.8 630.7 606.6 671.3 606.6 872.5 606.6 885.5 607.8 897.9 609.4 910.2 611.5 925.8 624.6 937.3 640.4 937.3H968.8C985.9 937.3 1000 923.2 1000 906.1V843.6C1000 826.6 985.9 812.5 968.8 812.5Z", + "width": 1000 + }, + "search": [ + "subscript" + ] + }, + { + "uid": "2f9853bb94503f2e5149dddae69657f6", + "css": "gauge", + "code": 59446, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M562.5 62.5C251.8 62.5 0 314.3 0 625 0 728.1 27.8 824.7 76.3 907.8 87.2 926.6 108.1 937.5 129.9 937.5H995.1C1016.9 937.5 1037.8 926.6 1048.7 907.8 1097.2 824.7 1125 728.1 1125 625 1125 314.3 873.2 62.5 562.5 62.5ZM562.5 187.5C591.2 187.5 614.4 207.3 621.7 233.7 619.6 238.1 616.6 242 615 246.7L597 300.8C587 307.6 575.5 312.5 562.5 312.5 528 312.5 500 284.5 500 250S528 187.5 562.5 187.5ZM187.5 750C153 750 125 722 125 687.5S153 625 187.5 625 250 653 250 687.5 222 750 187.5 750ZM281.3 437.5C246.7 437.5 218.8 409.5 218.8 375S246.7 312.5 281.3 312.5 343.8 340.5 343.8 375 315.8 437.5 281.3 437.5ZM763.2 296.1L643.4 655.4C670.2 678.4 687.5 712 687.5 750 687.5 772.9 680.9 794 670.2 812.5H454.8C444.1 794 437.5 772.9 437.5 750 437.5 683.7 489.3 630 554.5 625.8L674.3 266.4C682.4 241.9 708.9 228.4 733.6 236.8 758.1 245 771.4 271.5 763.2 296.1ZM791.9 407.8L822.2 316.9C828.9 314.4 836.1 312.5 843.8 312.5 878.3 312.5 906.3 340.5 906.3 375S878.3 437.5 843.8 437.5C821.5 437.5 802.9 425.3 791.9 407.8ZM937.5 750C903 750 875 722 875 687.5S903 625 937.5 625 1000 653 1000 687.5 972 750 937.5 750Z", + "width": 1125 + }, + "search": [ + "tachometer-alt" + ] + }, + { + "uid": "9f61e6a7ba9b929596aba1e946386ca1", + "css": "exchange-alt", + "code": 59447, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M0 328.1V296.9C0 271 21 250 46.9 250H750V156.3C750 114.5 800.6 93.7 830 123.1L986.3 279.4C1004.6 297.7 1004.6 327.3 986.3 345.6L830 501.9C800.7 531.2 750 510.7 750 468.8V375H46.9C21 375 0 354 0 328.1ZM953.1 625H250V531.3C250 489.6 199.5 468.6 170 498.1L13.7 654.4C-4.6 672.7-4.6 702.3 13.7 720.6L170 876.9C199.3 906.2 250 885.6 250 843.8V750H953.1C979 750 1000 729 1000 703.1V671.9C1000 646 979 625 953.1 625Z", + "width": 1000 + }, + "search": [ + "exchange-alt" + ] + }, + { + "uid": "762c1dbaf1d25d6f7365934483e90285", + "css": "text-width", + "code": 59448, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M31.3 62.5H843.8C861 62.5 875 76.5 875 93.8V281.3C875 298.5 861 312.5 843.8 312.5H774.4C757.2 312.5 743.2 298.5 743.2 281.3V187.5H511.2V437.5H578.1C595.4 437.5 609.4 451.5 609.4 468.8V531.3C609.4 548.5 595.4 562.5 578.1 562.5H296.9C279.6 562.5 265.6 548.5 265.6 531.3V468.8C265.6 451.5 279.6 437.5 296.9 437.5H363.8V187.5H131.8V281.3C131.8 298.5 117.8 312.5 100.6 312.5H31.3C14 312.5 0 298.5 0 281.3V93.8C0 76.5 14 62.5 31.3 62.5ZM865.8 727.9L709.6 571.7C691.4 553.4 656.3 563.2 656.3 593.8V687.5H218.8V593.8C218.8 565.8 184.9 552.1 165.4 571.7L9.2 727.9C-3 740.1-3.1 759.9 9.2 772.1L165.4 928.3C183.6 946.6 218.8 936.8 218.8 906.3V812.5H656.3V906.2C656.3 934.2 690.1 947.9 709.6 928.3L865.8 772.1C878 759.9 878.1 740.1 865.8 727.9Z", + "width": 875 + }, + "search": [ + "text-width" + ] + }, + { + "uid": "db94b783531717f104b39b398db3d0f2", + "css": "sync-alt", + "code": 59392, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M724.1 260.3C663 203.1 583.8 171.8 499.7 171.9 348.4 172 217.8 275.7 181.8 419.6 179.1 430.1 169.8 437.5 159 437.5H47.1C32.4 437.5 21.3 424.2 24 409.8 66.3 185.4 263.3 15.6 500 15.6 629.8 15.6 747.6 66.7 834.6 149.8L904.4 80C933.9 50.5 984.4 71.4 984.4 113.2V375C984.4 400.9 963.4 421.9 937.5 421.9H675.7C633.9 421.9 613 371.4 642.5 341.9L724.1 260.3ZM62.5 578.1H324.3C366.1 578.1 387 628.6 357.5 658.1L275.9 739.7C337 796.9 416.2 828.2 500.3 828.1 651.5 828 782.2 724.3 818.2 580.4 820.9 569.9 830.2 562.5 841 562.5H952.9C967.6 562.5 978.7 575.8 976 590.2 933.7 814.6 736.7 984.4 500 984.4 370.2 984.4 252.4 933.3 165.4 850.2L95.6 920C66.1 949.5 15.6 928.6 15.6 886.8V625C15.6 599.1 36.6 578.1 62.5 578.1Z", + "width": 1000 + }, + "search": [ + "sync-alt" + ] + }, + { + "uid": "f0ec8e32814f630fb6234b84cb5d4672", + "css": "picture", + "code": 59450, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M906.3 875H93.8C42 875 0 833 0 781.3V218.8C0 167 42 125 93.8 125H906.3C958 125 1000 167 1000 218.8V781.3C1000 833 958 875 906.3 875ZM218.8 234.4C158.3 234.4 109.4 283.3 109.4 343.8S158.3 453.1 218.8 453.1 328.1 404.2 328.1 343.8 279.2 234.4 218.8 234.4ZM125 750H875V531.3L704.1 360.3C694.9 351.2 680.1 351.2 670.9 360.3L406.3 625 297.8 516.6C288.7 507.4 273.8 507.4 264.7 516.6L125 656.3V750Z", + "width": 1000 + }, + "search": [ + "image" + ] + }, + { + "uid": "5c54164453ce690dddffa89377692bff", + "css": "file-code", + "code": 59401, + "src": "custom_icons", + "selected": true, + "svg": { + "path": "M750 238.2V250H500V0H511.8C524.3 0 536.2 4.9 545 13.7L736.3 205A46.9 46.9 0 0 1 750 238.2ZM484.4 312.5C458.6 312.5 437.5 291.4 437.5 265.6V0H46.9C21 0 0 21 0 46.9V953.1C0 979 21 1000 46.9 1000H703.1C729 1000 750 979 750 953.1V312.5H484.4ZM240.6 782.2A10.5 10.5 0 0 1 225.7 782.7L99 663.9A10.5 10.5 0 0 1 99 648.6L225.7 529.8A10.5 10.5 0 0 1 240.6 530.3L278.9 571.1A10.5 10.5 0 0 1 278.2 586.2L198.5 656.3 278.2 726.3A10.5 10.5 0 0 1 278.9 741.4L240.6 782.2ZM340.8 880.8L287.2 865.3A10.6 10.6 0 0 1 280 852.2L400 438.9A10.6 10.6 0 0 1 413.1 431.7L466.7 447.2A10.5 10.5 0 0 1 473.9 460.3L353.9 873.6A10.5 10.5 0 0 1 340.8 880.8ZM654.9 663.9L528.2 782.7A10.5 10.5 0 0 1 513.3 782.2L475 741.4A10.5 10.5 0 0 1 475.8 726.3L555.4 656.3 475.8 586.2A10.5 10.5 0 0 1 475 571.1L513.3 530.3A10.5 10.5 0 0 1 528.2 529.8L654.9 648.6A10.5 10.5 0 0 1 654.9 663.9Z", + "width": 750 + }, + "search": [ + "file-code" + ] } ] } \ No newline at end of file diff --git a/src/static/font/fontawesome-etherpad.eot b/src/static/font/fontawesome-etherpad.eot index 35a002de22b..abb48615f2c 100644 Binary files a/src/static/font/fontawesome-etherpad.eot and b/src/static/font/fontawesome-etherpad.eot differ diff --git a/src/static/font/fontawesome-etherpad.svg b/src/static/font/fontawesome-etherpad.svg index b69d0d974a2..fcc8fd360cf 100644 --- a/src/static/font/fontawesome-etherpad.svg +++ b/src/static/font/fontawesome-etherpad.svg @@ -1,128 +1,138 @@ -Copyright (C) 2018 by original authors @ fontello.com +Copyright (C) 2020 by original authors @ fontello.com - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + - + diff --git a/src/static/font/fontawesome-etherpad.ttf b/src/static/font/fontawesome-etherpad.ttf index 280a3d46018..683d0e11082 100644 Binary files a/src/static/font/fontawesome-etherpad.ttf and b/src/static/font/fontawesome-etherpad.ttf differ diff --git a/src/static/font/fontawesome-etherpad.woff b/src/static/font/fontawesome-etherpad.woff index c66051390e6..59373c06ce9 100644 Binary files a/src/static/font/fontawesome-etherpad.woff and b/src/static/font/fontawesome-etherpad.woff differ diff --git a/src/static/font/fontawesome-etherpad.woff2 b/src/static/font/fontawesome-etherpad.woff2 new file mode 100644 index 00000000000..0fd40b4647d Binary files /dev/null and b/src/static/font/fontawesome-etherpad.woff2 differ diff --git a/src/static/js/Changeset.js b/src/static/js/Changeset.js index 2458ae65ea6..e4e6d2d6391 100644 --- a/src/static/js/Changeset.js +++ b/src/static/js/Changeset.js @@ -791,6 +791,9 @@ exports.textLinesMutator = function (lines) { } } else { var sline = putCurLineInSplice(); + if (!curSplice[sline]) { + console.error("curSplice[sline] not populated, actual curSplice contents is ", curSplice, ". Possibly related to https://github.com/ether/etherpad-lite/issues/2802"); + } curSplice[sline] = curSplice[sline].substring(0, curCol) + text + curSplice[sline].substring(curCol); curCol += text.length; } @@ -1526,7 +1529,17 @@ exports.moveOpsToNewPool = function (cs, oldPool, newPool) { return upToDollar.replace(/\*([0-9a-z]+)/g, function (_, a) { var oldNum = exports.parseNum(a); var pair = oldPool.getAttrib(oldNum); - if(!pair) exports.error('Can\'t copy unknown attrib (reference attrib string to non-existant pool entry). Inconsistent attrib state!'); + + /* + * Setting an empty pair. Required for when delete pad contents / attributes + * while another user has the timeslider open. + * + * Fixes https://github.com/ether/etherpad-lite/issues/3932 + */ + if (!pair) { + pair = []; + } + var newNum = newPool.putAttrib(pair); return '*' + exports.numToString(newNum); }) + fromDollar; diff --git a/src/static/js/ace.js b/src/static/js/ace.js index 038ead7c231..d06d902a6ba 100644 --- a/src/static/js/ace.js +++ b/src/static/js/ace.js @@ -102,7 +102,15 @@ function Ace2Editor() var prefix = 'ace_'; var name = prefix + fnName; editor[fnName] = pendingInit(function(){ - info[prefix + fnName].apply(this, arguments); + if(fnName === "setAuthorInfo"){ + if(!arguments[0]){ + top.console.warn("setAuthorInfo AuthorId not set for some reason", arguments); + }else{ + info[prefix + fnName].apply(this, arguments); + } + }else{ + info[prefix + fnName].apply(this, arguments); + } }); }); @@ -217,7 +225,7 @@ function Ace2Editor() var iframeHTML = []; iframeHTML.push(doctype); - iframeHTML.push(""); + iframeHTML.push(""); // calls to these functions ($$INCLUDE_...) are replaced when this file is processed // and compressed, putting the compressed code from the named file directly into the @@ -308,7 +316,7 @@ window.onload = function () {\n\ }, 0);\n\ }'; - var outerHTML = [doctype, ''] + var outerHTML = [doctype, ''] var includedCSS = []; var $$INCLUDE_CSS = function(filename) {includedCSS.push(filename)}; diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index 64e49ce1591..b819ba498c5 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -69,12 +69,6 @@ function Ace2Inner(){ var THE_TAB = ' '; //4 var MAX_LIST_LEVEL = 16; - var LINE_NUMBER_PADDING_RIGHT = 4; - var LINE_NUMBER_PADDING_LEFT = 4; - var MIN_LINEDIV_WIDTH = 20; - var EDIT_BODY_PADDING_TOP = 8; - var EDIT_BODY_PADDING_LEFT = 8; - var FORMATTING_STYLES = ['bold', 'italic', 'underline', 'strikethrough']; var SELECT_BUTTON_CLASS = 'selected'; @@ -127,12 +121,6 @@ function Ace2Inner(){ var hasLineNumbers = true; var isStyled = true; - // space around the innermost iframe element - var iframePadLeft = MIN_LINEDIV_WIDTH + LINE_NUMBER_PADDING_RIGHT + EDIT_BODY_PADDING_LEFT; - var iframePadTop = EDIT_BODY_PADDING_TOP; - var iframePadBottom = 0, - iframePadRight = 0; - var console = (DEBUG && window.console); var documentAttributeManager; @@ -142,7 +130,7 @@ function Ace2Inner(){ console = {}; for (var i = 0; i < names.length; ++i) console[names[i]] = noop; - //console.error = function(str) { alert(str); }; + //top.console.error = function(str) { alert(str); }; } var PROFILER = window.PROFILER; @@ -267,15 +255,9 @@ function Ace2Inner(){ authorStyle.backgroundColor = bgcolor; parentAuthorStyle.backgroundColor = bgcolor; - // text contrast - if(colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.5) - { - authorStyle.color = '#ffffff'; - parentAuthorStyle.color = '#ffffff'; - }else{ - authorStyle.color = null; - parentAuthorStyle.color = null; - } + var textColor = colorutils.textColorFromBackgroundColor(bgcolor, parent.parent.clientVars.skinName); + authorStyle.color = textColor; + parentAuthorStyle.color = textColor; // anchor text contrast if(colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.55) @@ -292,6 +274,7 @@ function Ace2Inner(){ { if ((typeof author) != "string") { + top.console.error("Going to throw new error, potentially caused by: https://github.com/ether/etherpad-lite/issues/2802"); throw new Error("setAuthorInfo: author (" + author + ") is not a string"); } if (!info) @@ -396,7 +379,7 @@ function Ace2Inner(){ if (currentCallStack) { - console.error("Can't enter callstack " + type + ", already in " + currentCallStack.type); + top.console.error("Can't enter callstack " + type + ", already in " + currentCallStack.type); } var profiling = false; @@ -404,7 +387,7 @@ function Ace2Inner(){ function profileRest() { profiling = true; - console.profile(); + top.console.profile(); } function newEditEvent(eventType) @@ -494,7 +477,7 @@ function Ace2Inner(){ documentAttributeManager: documentAttributeManager }); - //console.log("Just did action for: "+type); + //top.console.log("Just did action for: "+type); cleanExit = true; } catch (e) @@ -510,7 +493,7 @@ function Ace2Inner(){ finally { var cs = currentCallStack; - //console.log("Finished action for: "+type); + //top.console.log("Finished action for: "+type); if (cleanExit) { submitOldEvent(cs.editEvent); @@ -544,7 +527,7 @@ function Ace2Inner(){ } } currentCallStack = null; - if (profiling) console.profileEnd(); + if (profiling) top.console.profileEnd(); } return result; } @@ -625,15 +608,6 @@ function Ace2Inner(){ }); }, 0); - // Chrome can't handle the truth.. If CSS rule white-space:pre-wrap - // is true then any paste event will insert two lines.. - // Sadly this will mean you get a walking Caret in Chrome when clicking on a URL - // So this has to be set to pre-wrap ;( - // We need to file a bug w/ the Chromium team. - if(browser.chrome){ - $("#innerdocbody").addClass("noprewrap"); - } - } function setStyled(newVal) @@ -763,6 +737,22 @@ function Ace2Inner(){ function setDocAText(atext) { + if (atext.text === "") { + /* + * The server is fine with atext.text being an empty string, but the front + * end is not, and crashes. + * + * It is not clear if this is a problem in the server or in the client + * code, and this is a client-side hack fix. The underlying problem needs + * to be investigated. + * + * See for reference: + * - https://github.com/ether/etherpad-lite/issues/3861 + */ + top.console.warn('atext.text is an empty string(""). Replacing with "\\n". See issue #3861.'); + atext.text = "\n"; + } + fastIncorp(8); var oldLen = rep.lines.totalWidth(); @@ -1076,7 +1066,7 @@ function Ace2Inner(){ function newTimeLimit(ms) { - //console.debug("new time limit"); + //top.console.debug("new time limit"); var startTime = now(); var lastElapsed = 0; var exceededAlready = false; @@ -1087,7 +1077,7 @@ function Ace2Inner(){ { if ((!printedTrace)) { // && now() - startTime - ms > 300) { - //console.trace(); + //top.console.trace(); printedTrace = true; } return true; @@ -1096,8 +1086,8 @@ function Ace2Inner(){ if (elapsed > ms) { exceededAlready = true; - //console.debug("time limit hit, before was %d/%d", lastElapsed, ms); - //console.trace(); + //top.console.debug("time limit hit, before was %d/%d", lastElapsed, ms); + //top.console.trace(); return true; } else @@ -1196,7 +1186,7 @@ function Ace2Inner(){ var isTimeUp = newTimeLimit(250); - //console.time("idlework"); + //top.console.time("idlework"); var finishedImportantWork = false; var finishedWork = false; @@ -1215,13 +1205,13 @@ function Ace2Inner(){ var visibleRange = scroll.getVisibleCharRange(rep); var docRange = [0, rep.lines.totalWidth()]; - //console.log("%o %o", docRange, visibleRange); + //top.console.log("%o %o", docRange, visibleRange); finishedImportantWork = true; finishedWork = true; } finally { - //console.timeEnd("idlework"); + //top.console.timeEnd("idlework"); if (finishedWork) { idleWorkTimer.atMost(1000); @@ -1304,7 +1294,7 @@ function Ace2Inner(){ selectionNeedsResetting = true; } - //if (timer()) console.dirxml(lineEntry.lineNode.dom); + //if (timer()) top.console.dirxml(lineEntry.lineNode.dom); if (firstLine === null) firstLine = lineIndex; lastLine = lineIndex; lineStart = lineEnd; @@ -1315,7 +1305,7 @@ function Ace2Inner(){ { currentCallStack.selectionAffected = true; } - //console.debug("Recolored line range %d-%d", firstLine, lastLine); + //top.console.debug("Recolored line range %d-%d", firstLine, lastLine); } // like getSpansForRange, but for a line, and the func takes (text,class) @@ -1521,7 +1511,7 @@ function Ace2Inner(){ observeSuspiciousNodes(); p.mark("dirty"); var dirtyRanges = getDirtyRanges(); - //console.log("dirtyRanges: "+toSource(dirtyRanges)); + //top.console.log("dirtyRanges: "+toSource(dirtyRanges)); var dirtyRangesCheckOut = true; var j = 0; var a, b; @@ -1555,8 +1545,8 @@ function Ace2Inner(){ p.mark("getsel"); var selection = getSelection(); - //console.log(magicdom.root.dom.innerHTML); - //console.log("got selection: %o", selection); + //top.console.log(magicdom.root.dom.innerHTML); + //top.console.log("got selection: %o", selection); var selStart, selEnd; // each one, if truthy, has [line,char] needed to set selection var i = 0; var splicesToDo = []; @@ -1604,7 +1594,7 @@ function Ace2Inner(){ // It could be SPAN or a DIV; basically this is any case where the contentCollector // decides it isn't done. // Note that this clean node might need to be there for the next dirty range. - //console.log("inclusive of "+lastDirtyNode.next().dom.tagName); + //top.console.log("inclusive of "+lastDirtyNode.next().dom.tagName); b++; var cleanLine = lastDirtyNode.nextSibling; cc.collectContent(cleanLine); @@ -1629,7 +1619,7 @@ function Ace2Inner(){ // Firefox isn't quite so bad, but it's still pretty quirky. var scrollToTheLeftNeeded = true; } - // console.log("Editor warning: " + linesWrapped + " long line" + (linesWrapped == 1 ? " was" : "s were") + " hard-wrapped into " + ccData.numLinesAfter + " lines."); + // top.console.log("Editor warning: " + linesWrapped + " long line" + (linesWrapped == 1 ? " was" : "s were") + " hard-wrapped into " + ccData.numLinesAfter + " lines."); } if (ss[0] >= 0) selStart = [ss[0] + a + netNumLinesChangeSoFar, ss[1]]; @@ -1693,7 +1683,7 @@ function Ace2Inner(){ if(n.parentNode) n.parentNode.removeChild(n); //dmesg(htmlPrettyEscape(htmlForRemovedChild(n))); - //console.log("removed: "+id); + //top.console.log("removed: "+id); }); if(scrollToTheLeftNeeded){ // needed to stop chrome from breaking the ui when long strings without spaces are pasted @@ -1913,7 +1903,7 @@ function Ace2Inner(){ { var line = lineAndChar[0]; var charsLeft = lineAndChar[1]; - //console.log("line: %d, key: %s, node: %o", line, rep.lines.atIndex(line).key, + //top.console.log("line: %d, key: %s, node: %o", line, rep.lines.atIndex(line).key, //getCleanNodeByKey(rep.lines.atIndex(line).key)); var lineEntry = rep.lines.atIndex(line); charsLeft -= lineEntry.lineMarker; @@ -2038,7 +2028,7 @@ function Ace2Inner(){ n = parNode; } } - if (n.id === "") console.debug("BAD"); + if (n.id === "") top.console.debug("BAD"); if (n.firstChild && isBlockElement(n.firstChild)) { col += 1; // lineMarker @@ -2925,11 +2915,11 @@ function Ace2Inner(){ } return true; - //console.log("selStart: %o, selEnd: %o, focusAtStart: %s", rep.selStart, rep.selEnd, + //top.console.log("selStart: %o, selEnd: %o, focusAtStart: %s", rep.selStart, rep.selEnd, //String(!!rep.selFocusAtStart)); } return false; - //console.log("%o %o %s", rep.selStart, rep.selEnd, rep.selFocusAtStart); + //top.console.log("%o %o %s", rep.selStart, rep.selEnd, rep.selFocusAtStart); } function isPadLoading(eventType) @@ -3162,14 +3152,14 @@ function Ace2Inner(){ // returns whether line was already correctly assigned (i.e. correctly // clean or dirty, according to cleanRanges, and if clean, correctly // attached or not attached (i.e. in the same range as) the prev and next lines). - //console.log("correctly assigning: %d", line); + //top.console.log("correctly assigning: %d", line); var rng = rangeForLine(line); var lineClean = isClean(line); if (rng < 0) { if (lineClean) { - console.debug("somehow lost clean line"); + top.console.debug("somehow lost clean line"); } return true; } @@ -3249,7 +3239,7 @@ function Ace2Inner(){ detectChangesAroundLine(N - 1, 1); p.mark("obs"); - //console.log("observedChanges: "+toSource(observedChanges)); + //top.console.log("observedChanges: "+toSource(observedChanges)); for (var k in observedChanges.cleanNodesNearChanges) { var key = k.substring(1); @@ -3680,17 +3670,6 @@ function Ace2Inner(){ var lineHeight = myselection.focusNode.offsetHeight; // line height of blank lines } - var heightOfChatIcon = parent.parent.$('#chaticon').height(); // height of the chat icon button - lineHeight = (lineHeight *2) + heightOfChatIcon; - var viewport = getViewPortTopBottom(); - var viewportHeight = viewport.bottom - viewport.top - lineHeight; - var relCaretOffsetTop = caretOffsetTop - viewport.top; // relative Caret Offset Top to viewport - if (viewportHeight < relCaretOffsetTop){ - parent.parent.$("#chaticon").css("opacity",".3"); // make chaticon opacity low when user types near it - }else{ - parent.parent.$("#chaticon").css("opacity","1"); // make chaticon opacity back to full (so fully visible) - } - //dmesg("keyevent type: "+type+", which: "+which); // Don't take action based on modifier keys going up and down. // Modifier keys do not generate "keypress" events. @@ -3876,6 +3855,9 @@ function Ace2Inner(){ fastIncorp(4); evt.preventDefault(); specialHandled = true; + + // close all gritters when the user hits escape key + parent.parent.$.gritter.removeAll(); } if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "s" && (evt.metaKey || evt.ctrlKey) && !evt.altKey && padShortcutEnabled.cmdS) /* Do a saved revision on ctrl S */ { @@ -4736,10 +4718,10 @@ function Ace2Inner(){ // can handle "backwards"-oriented selection, shift-arrow-keys move start // of selection browserSelection.collapse(end.container, end.offset); - //console.trace(); - //console.log(htmlPrettyEscape(rep.alltext)); - //console.log("%o %o", rep.selStart, rep.selEnd); - //console.log("%o %d", start.container, start.offset); + //top.console.trace(); + //top.console.log(htmlPrettyEscape(rep.alltext)); + //top.console.log("%o %o", rep.selStart, rep.selEnd); + //top.console.log("%o %d", start.container, start.offset); browserSelection.extend(start.container, start.offset); } else @@ -4774,70 +4756,7 @@ function Ace2Inner(){ return; } - function setIfNecessary(obj, prop, value) - { - if (obj[prop] != value) - { - obj[prop] = value; - } - } - - var lineNumberWidth = sideDiv.firstChild.offsetWidth; - var newSideDivWidth = lineNumberWidth + LINE_NUMBER_PADDING_LEFT; - if (newSideDivWidth < MIN_LINEDIV_WIDTH) newSideDivWidth = MIN_LINEDIV_WIDTH; - iframePadLeft = EDIT_BODY_PADDING_LEFT; - if (hasLineNumbers) iframePadLeft += newSideDivWidth + LINE_NUMBER_PADDING_RIGHT; - setIfNecessary(iframe.style, "left", iframePadLeft + "px"); - setIfNecessary(sideDiv.style, "width", newSideDivWidth + "px"); - - for (var i = 0; i < 2; i++) - { - var newHeight = root.clientHeight; - var newWidth = (browser.msie ? root.createTextRange().boundingWidth : root.clientWidth); - var viewHeight = getInnerHeight() - iframePadBottom - iframePadTop; - var viewWidth = getInnerWidth() - iframePadLeft - iframePadRight; - if (newHeight < viewHeight) - { - newHeight = viewHeight; - if (browser.msie) setIfNecessary(outerWin.document.documentElement.style, 'overflowY', 'auto'); - } - else - { - if (browser.msie) setIfNecessary(outerWin.document.documentElement.style, 'overflowY', 'scroll'); - } - if (doesWrap) - { - newWidth = viewWidth; - } - else - { - if (newWidth < viewWidth) newWidth = viewWidth; - } - setIfNecessary(iframe.style, "height", newHeight + "px"); - setIfNecessary(iframe.style, "width", newWidth + "px"); - setIfNecessary(sideDiv.style, "height", newHeight + "px"); - } - if (browser.firefox) - { - if (!doesWrap) - { - // the body:display:table-cell hack makes mozilla do scrolling - // correctly by shrinking the to fit around its content, - // but mozilla won't act on clicks below the body. We keep the - // style.height property set to the viewport height (editor height - // not including scrollbar), so it will never shrink so that part of - // the editor isn't clickable. - var body = root; - var styleHeight = viewHeight + "px"; - setIfNecessary(body.style, "height", styleHeight); - } - else - { - setIfNecessary(root.style, "height", ""); - } - } var win = outerWin; - var r = 20; enforceEditability(); @@ -5168,7 +5087,6 @@ function Ace2Inner(){ { var win = outerWin; var odoc = outerWin.document; - pixelX += iframePadLeft; var distInsideLeft = pixelX - win.scrollX; var distInsideRight = win.scrollX + getInnerWidth() - pixelX; if (distInsideLeft < 0) @@ -5366,7 +5284,7 @@ function Ace2Inner(){ function initLineNumbers() { lineNumbersShown = 1; - sideDiv.innerHTML = '
    1
    '; + sideDiv.innerHTML = '
    1
    '; sideDivInner = outerWin.document.getElementById("sidedivinner"); $(sideDiv).addClass("sidediv"); } diff --git a/src/static/js/broadcast.js b/src/static/js/broadcast.js index 1bd547f5275..380f69d6c39 100644 --- a/src/static/js/broadcast.js +++ b/src/static/js/broadcast.js @@ -125,7 +125,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro } else { - $("#padcontent").prepend(newDivs[i]); + $("#innerdocbody").prepend(newDivs[i]); } startDiv = newDivs[i]; } @@ -336,6 +336,11 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro var self = this; var path = revisionInfo.getPath(padContents.currentRevision, newRevision); debugLog('newRev: ', padContents.currentRevision, path); + + hooks.aCallAll('goToRevisionEvent', { + rev: newRevision + }); + if (path.status == 'complete') { var cs = path.changesets; @@ -543,12 +548,12 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro { // set up the currentDivs and DOM padContents.currentDivs = []; - $("#padcontent").html(""); + $("#innerdocbody").html(""); for (var i = 0; i < padContents.currentLines.length; i++) { var div = padContents.lineToElement(padContents.currentLines[i], padContents.alines[i]); padContents.currentDivs.push(div); - $("#padcontent").append(div); + $("#innerdocbody").append(div); } debugLog(padContents.currentDivs); }); diff --git a/src/static/js/broadcast_slider.js b/src/static/js/broadcast_slider.js index 1893994efe6..5f4325bbc33 100644 --- a/src/static/js/broadcast_slider.js +++ b/src/static/js/broadcast_slider.js @@ -41,16 +41,6 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) var savedRevisions = []; var sliderPlaying = false; - function disableSelection(element) - { - element.onselectstart = function() - { - return false; - }; - element.unselectable = "on"; - element.style.MozUserSelect = "none"; - element.style.cursor = "default"; - } var _callSliderCallbacks = function(newval) { sliderPos = newval; @@ -76,9 +66,8 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) newSavedRevision.addClass("star"); newSavedRevision.attr('pos', position); - newSavedRevision.css('position', 'absolute'); newSavedRevision.css('left', (position * ($("#ui-slider-bar").width() - 2) / (sliderLength * 1.0)) - 1); - $("#timeslider-slider").append(newSavedRevision); + $("#ui-slider-bar").append(newSavedRevision); newSavedRevision.mouseup(function(evt) { BroadcastSlider.setSliderPosition(position); @@ -122,27 +111,8 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) $("#revision_label").html(html10n.get("timeslider.version", { "version": newpos})); - if (newpos == 0) - { - $("#leftstar").css('opacity', .5); - $("#leftstep").css('opacity', .5); - } - else - { - $("#leftstar").css('opacity', 1); - $("#leftstep").css('opacity', 1); - } - - if (newpos == sliderLength) - { - $("#rightstar").css('opacity', .5); - $("#rightstep").css('opacity', .5); - } - else - { - $("#rightstar").css('opacity', 1); - $("#rightstep").css('opacity', 1); - } + $("#leftstar, #leftstep").toggleClass('disabled', newpos == 0); + $("#rightstar, #rightstep").toggleClass('disabled', newpos == sliderLength); sliderPos = newpos; _callSliderCallbacks(newpos); @@ -166,12 +136,6 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) padmodals.showModal("disconnected"); } - // Throttle seems like overkill here... Not sure why we do it! - var fixPadHeight = _.throttle(function(){ - var height = $('#timeslider-top').height(); - $('#editorcontainerbox').css({marginTop: height}); - }, 600); - function setAuthors(authors) { var authorsList = $("#authorsList"); @@ -230,8 +194,6 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) { authorsList.append(html10n.get("timeslider.toolbar.authorsList")); } - - fixPadHeight(); } BroadcastSlider = { @@ -283,66 +245,42 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) } // assign event handlers to html UI elements after page load - //$(window).load(function () fireWhenAllScriptsAreLoaded.push(function() { - disableSelection($("#playpause_button")[0]); - disableSelection($("#timeslider")[0]); - $(document).keyup(function(e) { - // If focus is on editbar, don't do anything - var target = $(':focus'); - if($(target).parents(".toolbar").length === 1){ - return; - } - var code = -1; if (!e) var e = window.event; - if (e.keyCode) code = e.keyCode; - else if (e.which) code = e.which; + var code = e.keyCode || e.which; if (code == 37) { // left - if (!e.shiftKey) - { - setSliderPosition(getSliderPosition() - 1); - } - else - { - var nextStar = 0; // default to first revision in document - for (var i = 0; i < savedRevisions.length; i++) - { - var pos = parseInt(savedRevisions[i].attr('pos')); - if (pos < getSliderPosition() && nextStar < pos) nextStar = pos; - } - setSliderPosition(nextStar); + if (e.shiftKey) { + $('#leftstar').click(); + } else { + $('#leftstep').click(); } } else if (code == 39) - { - if (!e.shiftKey) - { - setSliderPosition(getSliderPosition() + 1); - } - else - { - var nextStar = sliderLength; // default to last revision in document - for (var i = 0; i < savedRevisions.length; i++) - { - var pos = parseInt(savedRevisions[i].attr('pos')); - if (pos > getSliderPosition() && nextStar > pos) nextStar = pos; - } - setSliderPosition(nextStar); + { // right + if (e.shiftKey) { + $('#rightstar').click(); + } else { + $('#rightstep').click(); } } - else if (code == 32) playpause(); + else if (code == 32) + { // spacebar + $("#playpause_button_icon").trigger('click'); + } }); + // Resize $(window).resize(function() { updateSliderElements(); }); + // Slider click $("#ui-slider-bar").mousedown(function(evt) { $("#ui-slider-handle").css('left', (evt.clientX - $("#ui-slider-bar").offset().left)); @@ -386,57 +324,22 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) }) // play/pause toggling - $("#playpause_button").mousedown(function(evt) + $("#playpause_button_icon").click(function(evt) { - var self = this; - - // $(self).css('background-image', 'url(/static/img/crushed_button_depressed.png)'); - $(self).mouseup(function(evt2) - { - // $(self).css('background-image', 'url(/static/img/crushed_button_undepressed.png)'); - $(self).unbind('mouseup'); - BroadcastSlider.playpause(); - }); - $(document).mouseup(function(evt2) - { - // $(self).css('background-image', 'url(/static/img/crushed_button_undepressed.png)'); - $(document).unbind('mouseup'); - }); + BroadcastSlider.playpause(); }); // next/prev saved revision and changeset - $('.stepper').mousedown(function(evt) + $('.stepper').click(function(evt) { - var self = this; - var origcss = $(self).css('background-position'); - if (!origcss) - { - origcss = $(self).css('background-position-x') + " " + $(self).css('background-position-y'); - } - var origpos = parseInt(origcss.split(" ")[1]); - var newpos = (origpos - 43); - if (newpos < 0) newpos += 87; - - var newcss = (origcss.split(" ")[0] + " " + newpos + "px"); - if ($(self).css('opacity') != 1.0) newcss = origcss; - - $(self).css('background-position', newcss) - - $(self).mouseup(function(evt2) - { - $(self).css('background-position', origcss); - $(self).unbind('mouseup'); - $(document).unbind('mouseup'); - if ($(self).attr("id") == ("leftstep")) - { + switch ($(this).attr("id")) { + case "leftstep": setSliderPosition(getSliderPosition() - 1); - } - else if ($(self).attr("id") == ("rightstep")) - { + break; + case "rightstep": setSliderPosition(getSliderPosition() + 1); - } - else if ($(self).attr("id") == ("leftstar")) - { + break; + case "leftstar": var nextStar = 0; // default to first revision in document for (var i = 0; i < savedRevisions.length; i++) { @@ -444,9 +347,8 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) if (pos < getSliderPosition() && nextStar < pos) nextStar = pos; } setSliderPosition(nextStar); - } - else if ($(self).attr("id") == ("rightstar")) - { + break; + case "rightstar": var nextStar = sliderLength; // default to last revision in document for (var i = 0; i < savedRevisions.length; i++) { @@ -454,19 +356,13 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) if (pos > getSliderPosition() && nextStar > pos) nextStar = pos; } setSliderPosition(nextStar); - } - }); - $(document).mouseup(function(evt2) - { - $(self).css('background-position', origcss); - $(self).unbind('mouseup'); - $(document).unbind('mouseup'); - }); + break; + } }) if (clientVars) { - $("#timeslider").show(); + $("#timeslider-wrapper").show(); var startPos = clientVars.collab_client_vars.rev; if(window.location.hash.length > 1) diff --git a/src/static/js/chat.js b/src/static/js/chat.js old mode 100644 new mode 100755 index f9bb47c1b2c..a00ac9d9264 --- a/src/static/js/chat.js +++ b/src/static/js/chat.js @@ -30,12 +30,14 @@ var chat = (function() var self = { show: function () { - $("#chaticon").hide(); - $("#chatbox").show(); - $("#gritter-notice-wrapper").hide(); - self.scrollDown(); + $("#chaticon").removeClass('visible'); + $("#chatbox").addClass('visible'); + self.scrollDown(true); chatMentions = 0; Tinycon.setBubble(0); + $('.chat-gritter-msg').each(function() { + $.gritter.remove(this.id); + }); }, focus: function () { @@ -46,42 +48,33 @@ var chat = (function() stickToScreen: function(fromInitialCall) // Make chat stick to right hand side of screen { chat.show(); - if(!isStuck || fromInitialCall) { // Stick it to - padcookie.setPref("chatAlwaysVisible", true); - $('#chatbox').addClass("stickyChat"); - $('#titlesticky').hide(); - $('#editorcontainer').css({"right":"192px"}); - $('.stickyChat').css("top",$('#editorcontainer').offset().top+"px"); - isStuck = true; - } else { // Unstick it - padcookie.setPref("chatAlwaysVisible", false); - $('.stickyChat').css("top", "auto"); - $('#chatbox').removeClass("stickyChat"); - $('#titlesticky').show(); - $('#editorcontainer').css({"right":"0px"}); - isStuck = false; - } + isStuck = (!isStuck || fromInitialCall); + $('#chatbox').hide(); + // Add timeout to disable the chatbox animations + setTimeout(function() { + $('#chatbox, .sticky-container').toggleClass("stickyChat", isStuck); + $('#chatbox').css('display', 'flex'); + }, 0); + + padcookie.setPref("chatAlwaysVisible", isStuck); + $('#options-stickychat').prop('checked', isStuck); }, chatAndUsers: function(fromInitialCall) { var toEnable = $('#options-chatandusers').is(":checked"); if(toEnable || !userAndChat || fromInitialCall){ - padcookie.setPref("chatAndUsers", true); chat.stickToScreen(true); $('#options-stickychat').prop('checked', true) $('#options-chatandusers').prop('checked', true) $('#options-stickychat').prop("disabled", "disabled"); - $('#users').addClass("chatAndUsers"); - $("#chatbox").addClass("chatAndUsersChat"); - // redraw userAndChat = true; - padeditbar.redrawHeight() }else{ - padcookie.setPref("chatAndUsers", false); $('#options-stickychat').prop("disabled", false); - $('#users').removeClass("chatAndUsers"); - $("#chatbox").removeClass("chatAndUsersChat"); + userAndChat = false; } + padcookie.setPref("chatAndUsers", userAndChat); + $('#users, .sticky-container').toggleClass("chatAndUsers popup-show stickyUsers", userAndChat); + $("#chatbox").toggleClass("chatAndUsersChat", userAndChat); }, hide: function () { @@ -92,16 +85,14 @@ var chat = (function() } else { $("#chatcounter").text("0"); - $("#chaticon").show(); - $("#chatbox").hide(); - $.gritter.removeAll(); - $("#gritter-notice-wrapper").show(); + $("#chaticon").addClass('visible'); + $("#chatbox").removeClass('visible'); } }, - scrollDown: function() + scrollDown: function(force) { - if($('#chatbox').css("display") != "none"){ - if(!self.lastMessage || !self.lastMessage.position() || self.lastMessage.position().top < $('#chattext').height()) { + if ($('#chatbox').hasClass('visible')) { + if (force || !self.lastMessage || !self.lastMessage.position() || self.lastMessage.position().top < ($('#chattext').outerHeight() + 20)) { // if we use a slow animate here we can have a race condition when a users focus can not be moved away // from the last message recieved. $('#chattext').animate({scrollTop: $('#chattext')[0].scrollHeight}, { duration: 400, queue: false }); @@ -132,6 +123,16 @@ var chat = (function() var timeStr = hours + ":" + minutes; //create the authorclass + if (!msg.userId) { + /* + * If, for a bug or a database corruption, the message coming from the + * server does not contain the userId field (see for example #3731), + * let's be defensive and replace it with "unknown". + */ + msg.userId = "unknown"; + console.warn('The "userId" field of a chat message coming from the server was not present. Replacing with "unknown". This may be a bug or a database corruption.'); + } + var authorClass = "author-" + msg.userId.replace(/[^a-y0-9]/g, function(c) { if (c == ".") return "-"; @@ -149,21 +150,22 @@ var chat = (function() "text" : text, "sticky" : false, "timestamp" : msg.time, - "timeStr" : timeStr + "timeStr" : timeStr, + "duration" : 4000 } // is the users focus already in the chatbox? var alreadyFocused = $("#chatinput").is(":focus"); // does the user already have the chatbox open? - var chatOpen = $("#chatbox").is(":visible"); + var chatOpen = $("#chatbox").hasClass("visible"); // does this message contain this user's name? (is the curretn user mentioned?) var myName = $('#myusernameedit').val(); var wasMentioned = (text.toLowerCase().indexOf(myName.toLowerCase()) !== -1 && myName != "undefined"); if(wasMentioned && !alreadyFocused && !isHistoryAdd && !chatOpen) - { // If the user was mentioned show for twice as long and flash the browser window + { // If the user was mentioned, make the message sticky chatMentions++; Tinycon.setBubble(chatMentions); ctx.sticky = true; @@ -186,16 +188,13 @@ var chat = (function() count++; $("#chatcounter").text(count); - if(!chatOpen) { + if(!chatOpen && ctx.duration > 0) { $.gritter.add({ - // (string | mandatory) the heading of the notification - title: ctx.authorName, - // (string | mandatory) the text inside the notification - text: ctx.text, - // (bool | optional) if you want it to fade out on its own or just sit there + text: '' + ctx.authorName + '' + ctx.text, sticky: ctx.sticky, - // (int | optional) the time you want it to be alive for before fading out - time: '4000' + time: 5000, + position: 'bottom', + class_name: 'chat-gritter-msg' }); } } diff --git a/src/static/js/collab_client.js b/src/static/js/collab_client.js index 4bcc6ad2b3b..ca83af9dd31 100644 --- a/src/static/js/collab_client.js +++ b/src/static/js/collab_client.js @@ -313,6 +313,16 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) } else if (msg.type == "ACCEPT_COMMIT") { + /* + * this is the first time this user contributed to this pad. Let's record + * it, because it will be used for allowing import. + * + * TODO: here, we are changing this variable on the client side only. The + * server has all the informations to make the same deduction, and + * broadcast to the client. + */ + clientVars.thisUserHasEditedThisPad = true; + var newRev = msg.newRev; if (msgQueue.length > 0) { diff --git a/src/static/js/colorutils.js b/src/static/js/colorutils.js index af471c4538d..3faaebd3af9 100644 --- a/src/static/js/colorutils.js +++ b/src/static/js/colorutils.js @@ -142,4 +142,12 @@ colorutils.complementary = function(c) ]; } +colorutils.textColorFromBackgroundColor = function(bgcolor, skinName) +{ + var white = skinName == 'colibris' ? 'var(--super-light-color)' : '#fff'; + var black = skinName == 'colibris' ? 'var(--super-dark-color)' : '#222'; + + return colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.5 ? white : black; +} + exports.colorutils = colorutils; diff --git a/src/static/js/contentcollector.js b/src/static/js/contentcollector.js index d3bd7338340..446113a136a 100644 --- a/src/static/js/contentcollector.js +++ b/src/static/js/contentcollector.js @@ -526,6 +526,16 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas if (isPre) cc.incrementFlag(state, 'preMode'); var oldListTypeOrNull = null; var oldAuthorOrNull = null; + + // LibreOffice Writer puts in weird items during import or copy/paste, we should drop them. + if (cls === "Numbering_20_Symbols" || cls === "Bullet_20_Symbols") { + styl = null; + cls = null; + + // We have to return here but this could break things in the future, for now it shows how to fix the problem + return; + } + if (collectStyles) { hooks.callAll('collectContentPre', { @@ -655,7 +665,8 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas { if (lines.length() - 1 == startLine) { - cc.startNewLine(state); + // commented out to solve #2412 - https://github.com/ether/etherpad-lite/issues/2412 + // cc.startNewLine(state); } else { diff --git a/src/static/js/farbtastic.js b/src/static/js/farbtastic.js index 8a61627d298..acabea49d19 100644 --- a/src/static/js/farbtastic.js +++ b/src/static/js/farbtastic.js @@ -1,6 +1,7 @@ // Farbtastic 2.0 alpha +// edited by Sebastian Castro on 2020-04-06 (function ($) { - + var __debug = false; var __factor = 0.8; @@ -16,7 +17,7 @@ $.farbtastic = function (container, options) { $._farbtastic = function (container, options) { var fb = this; - + ///////////////////////////////////////////////////// /** @@ -134,7 +135,7 @@ $._farbtastic = function (container, options) { fb.ctxOverlay = fb.cnvOverlay[0].getContext('2d'); fb.ctxMask.translate(fb.mid, fb.mid); fb.ctxOverlay.translate(fb.mid, fb.mid); - + // Draw widget base layers. fb.drawCircle(); fb.drawMask(); @@ -208,7 +209,7 @@ $._farbtastic = function (container, options) { m.restore(); __debug && $('body').append('
    drawCircle '+ (+(new Date()) - tm) +'ms'); }; - + /** * Draw the saturation/luminance mask. */ @@ -232,9 +233,9 @@ $._farbtastic = function (container, options) { outputPixel(x, y, c, a); } - } + } } - + // Method #1: direct pixel access (new Canvas). if (fb.ctxMask.getImageData) { // Create half-resolution buffer. @@ -295,7 +296,7 @@ $._farbtastic = function (container, options) { } cache.push([c, a]); }); - } + } __debug && $('body').append('
    drawMask '+ (+(new Date()) - tm) +'ms'); } @@ -304,19 +305,17 @@ $._farbtastic = function (container, options) { */ fb.drawMarkers = function () { // Determine marker dimensions - var sz = options.width, lw = Math.ceil(fb.markerSize / 4), r = fb.markerSize - lw + 1; + var sz = options.width; var angle = fb.hsl[0] * 6.28, x1 = Math.sin(angle) * fb.radius, y1 = -Math.cos(angle) * fb.radius, x2 = 2 * fb.square * (.5 - fb.hsl[1]), - y2 = 2 * fb.square * (.5 - fb.hsl[2]), - c1 = fb.invert ? '#fff' : '#000', - c2 = fb.invert ? '#000' : '#fff'; + y2 = 2 * fb.square * (.5 - fb.hsl[2]); var circles = [ - { x: x1, y: y1, r: r, c: '#000', lw: lw + 1 }, - { x: x1, y: y1, r: fb.markerSize, c: '#fff', lw: lw }, - { x: x2, y: y2, r: r, c: c2, lw: lw + 1 }, - { x: x2, y: y2, r: fb.markerSize, c: c1, lw: lw }, + { x: x1, y: y1, r: fb.markerSize + 1, c: 'rgb(0,0,0,.4)', lw: 2 }, + { x: x1, y: y1, r: fb.markerSize, c: '#fff', lw: 2 }, + { x: x2, y: y2, r: fb.markerSize + 1, c: 'rgb(0,0,0,.4)', lw: 2 }, + { x: x2, y: y2, r: fb.markerSize, c: '#fff', lw: 2 }, ]; // Update the overlay canvas. @@ -343,7 +342,7 @@ $._farbtastic = function (container, options) { // Draw markers fb.drawMarkers(); - + // Linked elements or callback if (typeof fb.callback == 'object') { // Set background/foreground color @@ -363,15 +362,15 @@ $._farbtastic = function (container, options) { fb.callback.call(fb, fb.color); } } - + /** * Helper for returning coordinates relative to the center. */ fb.widgetCoords = function (event) { return { - x: event.pageX - fb.offset.left - fb.mid, + x: event.pageX - fb.offset.left - fb.mid, y: event.pageY - fb.offset.top - fb.mid - }; + }; } /** @@ -434,7 +433,7 @@ $._farbtastic = function (container, options) { fb.packDX = function (c, a) { return '#' + fb.dec2hex(a) + fb.dec2hex(c) + fb.dec2hex(c) + fb.dec2hex(c); }; - + fb.pack = function (rgb) { var r = Math.round(rgb[0] * 255); var g = Math.round(rgb[1] * 255); diff --git a/src/static/js/gritter.js b/src/static/js/gritter.js index 7f8c5b6eb6f..b0be20ffd24 100644 --- a/src/static/js/gritter.js +++ b/src/static/js/gritter.js @@ -7,6 +7,8 @@ * * Date: February 24, 2012 * Version: 1.7.4 + * + * Edited by Sebastian Castro on 2020-03-31 */ (function($){ @@ -14,16 +16,16 @@ * Set it up as an object under the jQuery namespace */ $.gritter = {}; - + /** * Set up global options that the user can over-ride */ $.gritter.options = { position: '', class_name: '', // could be set to 'gritter-light' to use white notifications - time: 6000 // hang on the screen for... + time: 3000 // hang on the screen for... } - + /** * Add a gritter notification to the screen * @see Gritter#add(); @@ -33,24 +35,24 @@ try { return Gritter.add(params || {}); } catch(e) { - + var err = 'Gritter Error: ' + e; - (typeof(console) != 'undefined' && console.error) ? - console.error(err, params) : + (typeof(console) != 'undefined' && console.error) ? + console.error(err, params) : alert(err); - + } - + } - + /** * Remove a gritter notification from the screen * @see Gritter#removeSpecific(); */ $.gritter.remove = function(id, params){ - Gritter.removeSpecific(id, params || {}); + Gritter.removeSpecific(id.split('gritter-item-')[1], params || {}); } - + /** * Remove all notifications * @see Gritter#stop(); @@ -58,28 +60,36 @@ $.gritter.removeAll = function(params){ Gritter.stop(params || {}); } - + /** * Big fat Gritter object * @constructor (not really since its object literal) */ var Gritter = { - + // Public - options to over-ride with $.gritter.options in "add" - position: '', - fade_in_speed: '', - fade_out_speed: '', time: '', - + // Private - no touchy the private parts _custom_timer: 0, _item_count: 0, _is_setup: 0, - _tpl_close: '
    ', - _tpl_title: '[[title]]', - _tpl_item: '', - _tpl_wrap: '
    ', - + _tpl_wrap_top: '
    ', + _tpl_wrap_bottom: '
    ', + _tpl_close: '', + _tpl_title: '

    [[title]]

    ', + _tpl_item: [ + ''].join(''), + + /** * Add a gritter notification to the screen * @param {Object} params The object that contains all the options for drawing the notification @@ -93,29 +103,33 @@ // We might have some issues if we don't have a title or text! if(!params.text){ - throw 'You must supply "text" parameter.'; + throw 'You must supply "text" parameter.'; } - + // Check the options and set them once if(!this._is_setup){ this._runSetup(); } - + // Basics - var title = params.title, + var title = params.title, text = params.text, image = params.image || '', + position = params.position || 'top', sticky = params.sticky || false, item_class = params.class_name || $.gritter.options.class_name, - position = $.gritter.options.position, time_alive = params.time || ''; this._verifyWrapper(); - + + if (sticky) { + item_class += " sticky"; + } + this._item_count++; - var number = this._item_count, + var number = this._item_count, tmp = this._tpl_item; - + // Assign callbacks $(['before_open', 'after_open', 'before_close', 'after_close']).each(function(i, val){ Gritter['_' + val + '_' + number] = ($.isFunction(params[val])) ? params[val] : function(){} @@ -123,25 +137,22 @@ // Reset this._custom_timer = 0; - + // A custom fade time set if(time_alive){ this._custom_timer = time_alive; } - - var image_str = (image != '') ? '' : '', - class_name = (image != '') ? 'gritter-with-image' : 'gritter-without-image'; - + // String replacements on the template if(title){ title = this._str_replace('[[title]]',title,this._tpl_title); }else{ title = ''; } - + tmp = this._str_replace( - ['[[title]]', '[[text]]', '[[close]]', '[[image]]', '[[number]]', '[[class_name]]', '[[item_class]]'], - [title, text, this._tpl_close, image_str, this._item_count, class_name, item_class], tmp + ['[[title]]', '[[text]]', '[[number]]', '[[item_class]]'], + [title, text, this._item_count, item_class], tmp ); // If it's false, don't show another gritter message @@ -149,42 +160,37 @@ return false; } - $('#gritter-notice-wrapper').addClass(position).append(tmp); - + if (['top', 'bottom'].indexOf(position) == -1) { + position = 'top'; + } + + $('#gritter-container.' + position).append(tmp); + var item = $('#gritter-item-' + this._item_count); - - item.fadeIn(this.fade_in_speed, function(){ - Gritter['_after_open_' + number]($(this)); - }); - + + setTimeout(function() { item.addClass('popup-show'); }, 0); + Gritter['_after_open_' + number](item); + if(!sticky){ this._setFadeTimer(item, number); + // Bind the hover/unhover states + $(item).on('mouseenter', function(event) { + Gritter._restoreItemIfFading($(this), number); + }); + $(item).on('mouseleave', function(event) { + Gritter._setFadeTimer($(this), number); + }); } - - // Bind the hover/unhover states - $(item).bind('mouseenter mouseleave', function(event){ - if(event.type == 'mouseenter'){ - if(!sticky){ - Gritter._restoreItemIfFading($(this), number); - } - } - else { - if(!sticky){ - Gritter._setFadeTimer($(this), number); - } - } - Gritter._hoverState($(this), event.type); - }); - + // Clicking (X) makes the perdy thing close $(item).find('.gritter-close').click(function(){ Gritter.removeSpecific(number, {}, null, true); }); - + return number; - + }, - + /** * If we don't have any more gritter notifications, get rid of the wrapper using this check * @private @@ -193,89 +199,55 @@ * @param {Boolean} manual_close Did we close the gritter dialog with the (X) button */ _countRemoveWrapper: function(unique_id, e, manual_close){ - + // Remove it then run the callback function e.remove(); this['_after_close_' + unique_id](e, manual_close); - - // Check if the wrapper is empty, if it is.. remove the wrapper - if($('.gritter-item-wrapper').length == 0){ - $('#gritter-notice-wrapper').remove(); - } - + + // Remove container if empty + $('#gritter-container').each(function() { + if ($(this).find('.gritter-item').length == 0) { + $(this).remove(); + } + }) }, - + /** * Fade out an element after it's been on the screen for x amount of time * @private * @param {Object} e The jQuery element to get rid of * @param {Integer} unique_id The id of the element to remove - * @param {Object} params An optional list of params to set fade speeds etc. + * @param {Object} params An optional list of params. * @param {Boolean} unbind_events Unbind the mouseenter/mouseleave events if they click (X) */ _fade: function(e, unique_id, params, unbind_events){ var params = params || {}, fade = (typeof(params.fade) != 'undefined') ? params.fade : true, - fade_out_speed = params.speed || this.fade_out_speed, manual_close = unbind_events; this['_before_close_' + unique_id](e, manual_close); - + // If this is true, then we are coming from clicking the (X) if(unbind_events){ e.unbind('mouseenter mouseleave'); } - + // Fade it out or remove it if(fade){ - - e.animate({ - opacity: 0 - }, fade_out_speed, function(){ - e.animate({ height: 0 }, 300, function(){ - Gritter._countRemoveWrapper(unique_id, e, manual_close); - }) - }) - + e.removeClass('popup-show'); + setTimeout(function() { + Gritter._countRemoveWrapper(unique_id, e, manual_close); + }, 300) } else { - + this._countRemoveWrapper(unique_id, e); - - } - - }, - - /** - * Perform actions based on the type of bind (mouseenter, mouseleave) - * @private - * @param {Object} e The jQuery element - * @param {String} type The type of action we're performing: mouseenter or mouseleave - */ - _hoverState: function(e, type){ - - // Change the border styles and add the (X) close button when you hover - if(type == 'mouseenter'){ - - e.addClass('hover'); - - // Show close button - e.find('.gritter-close').show(); - - } - // Remove the border styles and hide (X) close button when you mouse out - else { - - e.removeClass('hover'); - - // Hide close button - e.find('.gritter-close').hide(); - + } - + }, - + /** * Remove a specific notification based on an ID * @param {Integer} unique_id The ID used to delete a specific notification @@ -284,17 +256,17 @@ * @param {Boolean} unbind_events If we clicked on the (X) we set this to true to unbind mouseenter/mouseleave */ removeSpecific: function(unique_id, params, e, unbind_events){ - + if(!e){ var e = $('#gritter-item-' + unique_id); } - // We set the fourth param to let the _fade function know to + // We set the fourth param to let the _fade function know to // unbind the "mouseleave" event. Once you click (X) there's no going back! this._fade(e, unique_id, params || {}, unbind_events); - + }, - + /** * If the item is fading out and we hover over it, restore it! * @private @@ -302,114 +274,116 @@ * @param {Integer} unique_id The ID of the element */ _restoreItemIfFading: function(e, unique_id){ - + clearTimeout(this['_int_id_' + unique_id]); e.stop().css({ opacity: '', height: '' }); - + }, - + /** * Setup the global options - only once * @private */ _runSetup: function(){ - + for(opt in $.gritter.options){ this[opt] = $.gritter.options[opt]; } this._is_setup = 1; - + }, - + /** * Set the notification to fade out after a certain amount of time * @private * @param {Object} item The HTML element we're dealing with * @param {Integer} unique_id The ID of the element */ - _setFadeTimer: function(e, unique_id){ - + _setFadeTimer: function(item, unique_id){ + var timer_str = (this._custom_timer) ? this._custom_timer : this.time; - this['_int_id_' + unique_id] = setTimeout(function(){ - Gritter._fade(e, unique_id); + this['_int_id_' + unique_id] = setTimeout(function(){ + Gritter._fade(item, unique_id); }, timer_str); - + }, - + /** * Bring everything to a halt * @param {Object} params A list of callback functions to pass when all notifications are removed - */ + */ stop: function(params){ - + // callbacks (if passed) var before_close = ($.isFunction(params.before_close)) ? params.before_close : function(){}; var after_close = ($.isFunction(params.after_close)) ? params.after_close : function(){}; - - var wrap = $('#gritter-notice-wrapper'); + + var wrap = $('#gritter-container'); before_close(wrap); wrap.fadeOut(function(){ $(this).remove(); after_close(); }); - + }, - + /** * An extremely handy PHP function ported to JS, works well for templating * @private * @param {String/Array} search A list of things to search for * @param {String/Array} replace A list of things to replace the searches with * @return {String} sa The output - */ + */ _str_replace: function(search, replace, subject, count){ - + var i = 0, j = 0, temp = '', repl = '', sl = 0, fl = 0, f = [].concat(search), r = [].concat(replace), s = subject, ra = r instanceof Array, sa = s instanceof Array; s = [].concat(s); - + if(count){ this.window[count] = 0; } - + for(i = 0, sl = s.length; i < sl; i++){ - + if(s[i] === ''){ continue; } - + for (j = 0, fl = f.length; j < fl; j++){ - + temp = s[i] + ''; repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0]; s[i] = (temp).split(f[j]).join(repl); - + if(count && s[i] !== temp){ this.window[count] += (temp.length-s[i].length) / f[j].length; } - + } } - + return sa ? s : s[0]; - + }, - + /** * A check to make sure we have something to wrap our notices with * @private - */ + */ _verifyWrapper: function(){ - - if($('#gritter-notice-wrapper').length == 0){ - $('body').append(this._tpl_wrap); + if ($('#gritter-container.top').length === 0) { + $('#editorcontainerbox').append(this._tpl_wrap_top); + } + + if ($('#gritter-container.bottom').length === 0) { + $('#editorcontainerbox').append(this._tpl_wrap_bottom); } - } - + } - + })(jQuery); diff --git a/src/static/js/html10n.js b/src/static/js/html10n.js index 8fbc6f64344..ee7eec0a77d 100644 --- a/src/static/js/html10n.js +++ b/src/static/js/html10n.js @@ -179,18 +179,40 @@ window.html10n = (function(window, document, undefined) { return } - // dat alng ain't here, man! + // Check if lang exists if (!data[lang]) { - var msg = 'Couldn\'t find translations for '+lang - , l - if(~lang.indexOf('-')) lang = lang.split('-')[0] // then let's try related langs - for(l in data) { - if(lang != l && l.indexOf(lang) === 0 && data[l]) { - lang = l - break; + // lang not found + // This may be due to formatting (expected 'ru' but browser sent 'ru-RU') + // Set err msg before mutating lang (we may need this later) + var msg = 'Couldn\'t find translations for ' + lang; + + // Check for '-' ('ROOT-VARIANT') + if (lang.indexOf('-') > -1) { + // ROOT-VARIANT formatting detected + lang = lang.split('-')[0]; // set lang to ROOT lang + } + + // Check if ROOT lang exists (e.g 'ru') + if (!data[lang]) { + // ROOT lang not found. (e.g 'zh') + // Loop through langs data. Maybe we have a variant? e.g (zh-hans) + var l; // langs item. Declare outside of loop + + for (l in data) { + // Is not ROOT? + // And index of ROOT equals 0? + // And is known lang? + if (lang != l && l.indexOf(lang) === 0 && data[l]) { + lang = l; // set lang to ROOT-VARIANT (e.g 'zh-hans') + break; + } + } + + // Did we find a variant? If not, return err. + if (lang != l) { + return cb(new Error(msg)); } } - if(lang != l) return cb(new Error(msg)) } if ('string' == typeof data[lang]) { diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 69fa659026c..622b57f3edb 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -73,7 +73,7 @@ function randomString() // callback: the function to call when all above succeeds, `val` is the value supplied by the user var getParameters = [ { name: "noColors", checkVal: "true", callback: function(val) { settings.noColors = true; $('#clearAuthorship').hide(); } }, - { name: "showControls", checkVal: "false", callback: function(val) { $('#editbar').addClass('hideControlsEditbar'); $('#editorcontainer').addClass('hideControlsEditor'); } }, + { name: "showControls", checkVal: "true", callback: function(val) { $('#editbar').css('display', 'flex') } }, { name: "showChat", checkVal: "true", callback: function(val) { $('#chaticon').show(); } }, { name: "showLineNumbers", checkVal: "false", callback: function(val) { settings.LineNumbersDisabled = true; } }, { name: "useMonospaceFont", checkVal: "true", callback: function(val) { settings.useMonospaceFontGlobal = true; } }, @@ -364,12 +364,6 @@ function handshake() }); } -$.extend($.gritter.options, { - position: 'bottom-right', // defaults to 'top-right' but can be 'bottom-left', 'bottom-right', 'top-left', 'top-right' (added in 1.7.1) - fade: false, // dont fade, too jerky on mobile - time: 6000 // hang on the screen for... -}); - var pad = { // don't access these directly from outside this file, except // for debugging @@ -428,6 +422,11 @@ var pad = { }, switchToPad: function(padId) { + // destroy old pad from DOM + // See https://github.com/ether/etherpad-lite/pull/3915 + // TODO: Check if Destroying is enough and doesn't leave negative stuff + // See ace.js "editor.destroy" for a reference of how it was done before + $('#editorcontainer').find("iframe")[0].remove(); var options = document.location.href.split('?')[1]; var newHref = padId; if (typeof options != "undefined" && options != null){ @@ -561,6 +560,18 @@ var pad = { pad.changeViewOption('rtlIsTrue', true); } pad.changeViewOption('padFontFamily', padcookie.getPref("padFontFamily")); + $('#viewfontmenu').val(padcookie.getPref("padFontFamily")).niceSelect('update'); + + // Prevent sticky chat or chat and users to be checked for mobiles + function checkChatAndUsersVisibility(x) { + if (x.matches) { // If media query matches + $('#options-chatandusers:checked').click(); + $('#options-stickychat:checked').click(); + } + } + var mobileMatch = window.matchMedia("(max-width: 800px)"); + mobileMatch.addListener(checkChatAndUsersVisibility); // check if window resized + setTimeout(function() { checkChatAndUsersVisibility(mobileMatch); }, 0); // check now after load hooks.aCallAll("postAceInit", {ace: padeditor.ace, pad: pad}); } diff --git a/src/static/js/pad_editbar.js b/src/static/js/pad_editbar.js index 9cf357aadd5..ba2171b0db8 100644 --- a/src/static/js/pad_editbar.js +++ b/src/static/js/pad_editbar.js @@ -24,6 +24,8 @@ var hooks = require('./pluginfw/hooks'); var padutils = require('./pad_utils').padutils; var padeditor = require('./pad_editor').padeditor; var padsavedrevs = require('./pad_savedrevs'); +var _ = require('ep_etherpad-lite/static/js/underscore'); +require('ep_etherpad-lite/static/js/vendors/nice-select'); var ToolbarItem = function (element) { this.$el = element; @@ -141,11 +143,6 @@ var padeditbar = (function() init: function() { var self = this; self.dropdowns = []; - // Listen for resize events (sucks but needed as iFrame ace_inner has to be position absolute - // A CSS fix for this would be nice but I'm not sure how we'd do it. - $(window).resize(function(){ - self.redrawHeight(); - }); $("#editbar .editbarbutton").attr("unselectable", "on"); // for IE $("#editbar").removeClass("disabledtoolbar").addClass("enabledtoolbar"); @@ -160,9 +157,11 @@ var padeditbar = (function() bodyKeyEvent(evt); }); - $('#editbar').show(); - - this.redrawHeight(); + $('.show-more-icon-btn').click(function() { + $('.toolbar').toggleClass('full-icons'); + }); + self.checkAllIconsAreDisplayedInToolbar(); + $(window).resize(_.debounce( self.checkAllIconsAreDisplayedInToolbar, 100 ) ); registerDefaultCommands(self); @@ -170,10 +169,16 @@ var padeditbar = (function() toolbar: self, ace: padeditor.ace }); + + $('select').niceSelect(); + + // When editor is scrolled, we add a class to style the editbar differently + $('iframe[name="ace_outer"]').contents().scroll(function() { + $('#editbar').toggleClass('editor-scrolled', $(this).scrollTop() > 2); + }) }, isEnabled: function() { -// return !$("#editbar").hasClass('disabledtoolbar'); return true; }, disable: function() @@ -185,55 +190,6 @@ var padeditbar = (function() this.commands[cmd] = callback; return this; }, - calculateEditbarHeight: function() { - // if we're on timeslider, there is nothing on editbar, so we just use zero - var onTimeslider = $('.menu_left').length === 0; - if (onTimeslider) return 0; - - // if editbar has both menu left and right, its height must be - // the max between the height of these two parts - var leftMenuPosition = $('.menu_left').offset().top; - var rightMenuPosition = $('.menu_right').offset().top; - var editbarHasMenuLeftAndRight = (leftMenuPosition === rightMenuPosition); - - var height; - if (editbarHasMenuLeftAndRight) { - height = Math.max($('.menu_left').height(), $('.menu_right').height()); - } - else { - height = $('.menu_left').height(); - } - - return height; - }, - redrawHeight: function(){ - var minimunEditbarHeight = self.calculateEditbarHeight(); - var editbarHeight = minimunEditbarHeight + 1 + "px"; - var containerTop = minimunEditbarHeight + 6 + "px"; - $('#editbar').css("height", editbarHeight); - - $('#editorcontainer').css("top", containerTop); - - // make sure pop ups are in the right place - if($('#editorcontainer').offset()){ - $('.popup').css("top", $('#editorcontainer').offset().top + "px"); - } - - // If sticky chat is enabled.. - if($('#options-stickychat').is(":checked")){ - if($('#editorcontainer').offset()){ - $('#chatbox').css("top", $('#editorcontainer').offset().top + "px"); - } - }; - - // If chat and Users is enabled.. - if($('#options-chatandusers').is(":checked")){ - if($('#editorcontainer').offset()){ - $('#users').css("top", $('#editorcontainer').offset().top + "px"); - } - } - - }, registerDropdownCommand: function (cmd, dropdown) { dropdown = dropdown || cmd; self.dropdowns.push(dropdown) @@ -256,6 +212,14 @@ var padeditbar = (function() }, toggleDropDown: function(moduleName, cb) { + // do nothing if users are sticked + if (moduleName === "users" && $('#users').hasClass('stickyUsers')) { + return; + } + + $('.nice-select').removeClass('open'); + $('.toolbar-popup').removeClass("popup-show"); + // hide all modules and remove highlighting of all buttons if(moduleName == "none") { @@ -274,14 +238,12 @@ var padeditbar = (function() var isAForceReconnectMessage = module.find('button#forcereconnect:visible').length > 0; if(isAForceReconnectMessage) continue; - - if(module.css('display') != "none") - { + if (module.hasClass('popup-show')) { $("li[data-key=" + thisModuleName + "] > a").removeClass("selected"); - module.slideUp("fast", cb); - returned = true; + module.removeClass("popup-show"); } } + if(!returned && cb) return cb(); } else @@ -293,15 +255,18 @@ var padeditbar = (function() var thisModuleName = self.dropdowns[i]; var module = $("#" + thisModuleName); - if(module.css('display') != "none") + if(module.hasClass('popup-show')) { $("li[data-key=" + thisModuleName + "] > a").removeClass("selected"); - module.slideUp("fast"); + module.removeClass("popup-show"); } else if(thisModuleName==moduleName) { $("li[data-key=" + thisModuleName + "] > a").addClass("selected"); - module.slideDown("fast", cb); + module.addClass("popup-show"); + if (cb) { + cb(); + } } } } @@ -332,6 +297,15 @@ var padeditbar = (function() $('#embedinput').val(''); $('#linkinput').val(padurl); } + }, + checkAllIconsAreDisplayedInToolbar: function() + { + // reset style + $('.toolbar').removeClass('cropped') + var menu_left = $('.toolbar .menu_left')[0]; + if (menu_left && menu_left.scrollWidth > $('.toolbar').width()) { + $('.toolbar').addClass('cropped'); + } } }; @@ -352,7 +326,7 @@ var padeditbar = (function() // Timeslider probably.. // Shift focus away from any drop downs $(':focus').blur(); // required to do not try to remove! - $('#padmain').focus(); // Focus back onto the pad + $('#editorcontainerbox').focus(); // Focus back onto the pad }else{ // Shift focus away from any drop downs $(':focus').blur(); // required to do not try to remove! @@ -420,6 +394,17 @@ var padeditbar = (function() toolbar.registerCommand("import_export", function () { toolbar.toggleDropDown("import_export", function(){ + + if (clientVars.thisUserHasEditedThisPad) { + // the user has edited this pad historically or in this session + $('#importform').show(); + $('#importmessagepermission').hide(); + } else { + // this is the first time this user visits this pad + $('#importform').hide(); + $('#importmessagepermission').show(); + } + // If Import file input exists then focus on it.. if($('#importfileinput').length !== 0){ setTimeout(function(){ diff --git a/src/static/js/pad_editor.js b/src/static/js/pad_editor.js index c59a2fc615d..b035bf6fc3d 100644 --- a/src/static/js/pad_editor.js +++ b/src/static/js/pad_editor.js @@ -134,6 +134,7 @@ var padeditor = (function() v = getOption('showAuthorColors', true); self.ace.setProperty("showsauthorcolors", v); + $('#chattext').toggleClass('authorColors', v); padutils.setCheckbox($("#options-colorscheck"), v); // Override from parameters if true @@ -141,29 +142,7 @@ var padeditor = (function() self.ace.setProperty("showsauthorcolors", !settings.noColors); } - var fontFamily = newOptions['padFontFamily']; - switch (fontFamily) { - case "monospace": self.ace.setProperty("textface", "monospace"); break; - case "montserrat": self.ace.setProperty("textface", "Montserrat"); break; - case "opendyslexic": self.ace.setProperty("textface", "OpenDyslexic"); break; - case "comicsans": self.ace.setProperty("textface", "'Comic Sans MS','Comic Sans',cursive"); break; - case "georgia": self.ace.setProperty("textface", "Georgia,'Bitstream Charter',serif"); break; - case "impact": self.ace.setProperty("textface", "Impact,Haettenschweiler,'Arial Black',sans-serif"); break; - case "lucida": self.ace.setProperty("textface", "Lucida,'Lucida Serif','Lucida Bright',serif"); break; - case "lucidasans": self.ace.setProperty("textface", "'Lucida Sans','Lucida Grande','Lucida Sans Unicode','Luxi Sans',sans-serif"); break; - case "palatino": self.ace.setProperty("textface", "Palatino,'Palatino Linotype','URW Palladio L',Georgia,serif"); break; - case "robotomono": self.ace.setProperty("textface", "RobotoMono"); break; - case "tahoma": self.ace.setProperty("textface", "Tahoma,sans-serif"); break; - case "timesnewroman": self.ace.setProperty("textface", "'Times New Roman',Times,serif"); break; - case "trebuchet": self.ace.setProperty("textface", "'Trebuchet MS',sans-serif"); break; - case "verdana": self.ace.setProperty("textface", "Verdana,'DejaVu Sans',sans-serif"); break; - case "symbol": self.ace.setProperty("textface", "Symbol"); break; - case "webdings": self.ace.setProperty("textface", "Webdings"); break; - case "wingdings": self.ace.setProperty("textface", "Wingdings"); break; - case "sansserif": self.ace.setProperty("textface", "sans-serif"); break; - case "serif": self.ace.setProperty("textface", "serif"); break; - default: self.ace.setProperty("textface", ""); break; - } + self.ace.setProperty("textface", newOptions['padFontFamily'] || ""); }, dispose: function() { diff --git a/src/static/js/pad_impexp.js b/src/static/js/pad_impexp.js index 70220f87eab..ac4982102f6 100644 --- a/src/static/js/pad_impexp.js +++ b/src/static/js/pad_impexp.js @@ -111,6 +111,10 @@ var padimpexp = (function() msg = html10n.get("pad.impexp.uploadFailed"); } else if(status === "padHasData"){ msg = html10n.get("pad.impexp.padHasData"); + } else if(status === "maxFileSize"){ + msg = html10n.get("pad.impexp.maxFileSize"); + } else if(status === "permission"){ + msg = html10n.get("pad.impexp.permission"); } function showError(fade) @@ -244,7 +248,17 @@ var padimpexp = (function() { importFailed(status); } - if(directDatabaseAccess) pad.switchToPad(clientVars.padId); + else + { + $('#import_export').removeClass('popup-show'); + } + + if (directDatabaseAccess) { + // Switch to the pad without redrawing the page + pad.switchToPad(clientVars.padId); + $('#import_export').removeClass('popup-show'); + } + importDone(); }, disable: function() diff --git a/src/static/js/pad_modals.js b/src/static/js/pad_modals.js index 2fc621dc4b6..f965bc600d3 100644 --- a/src/static/js/pad_modals.js +++ b/src/static/js/pad_modals.js @@ -44,10 +44,11 @@ var padmodals = (function() }); }, showOverlay: function() { - $("#overlay").show(); + // Prevent the user to interact with the toolbar. Useful when user is disconnected for example + $("#toolbar-overlay").show(); }, hideOverlay: function() { - $("#overlay").hide(); + $("#toolbar-overlay").hide(); } }; return self; diff --git a/src/static/js/pad_savedrevs.js b/src/static/js/pad_savedrevs.js index 34323b22fc9..cb2198a5584 100644 --- a/src/static/js/pad_savedrevs.js +++ b/src/static/js/pad_savedrevs.js @@ -25,8 +25,8 @@ exports.saveNow = function(){ text: _("pad.savedrevs.timeslider") || "You can view saved revisions in the timeslider", // (bool | optional) if you want it to fade out on its own or just sit there sticky: false, - // (int | optional) the time you want it to be alive for before fading out - time: '2000' + time: 3000, + class_name: "saved-revision", }); } diff --git a/src/static/js/pad_userlist.js b/src/static/js/pad_userlist.js index 7ac960d074b..02e6add587e 100644 --- a/src/static/js/pad_userlist.js +++ b/src/static/js/pad_userlist.js @@ -207,6 +207,7 @@ var paduserlist = (function() tr = $(getRowHtml(domId, getEmptyRowHtml(getAnimationHeight(ANIMATION_START)), authorId)); } handleRowNode(tr, data); + $("table#otheruserstable").show(); if (position == 0) { $("table#otheruserstable").prepend(tr); @@ -263,6 +264,9 @@ var paduserlist = (function() scheduleAnimation(); } } + if (rowsPresent.length === 0) { + $("table#otheruserstable").hide(); + } } // newPosition is position after the row has been removed @@ -421,20 +425,6 @@ var paduserlist = (function() jqueryNode.removeAttr('disabled').addClass('editable'); } - function updateInviteNotice() - { - if (otherUsersInfo.length == 0) - { - $("#otheruserstable").hide(); - $("#nootherusers").show(); - } - else - { - $("#nootherusers").hide(); - $("#otheruserstable").show(); - } - } - var knocksToIgnore = {}; var guestPromptFlashState = 0; var guestPromptFlash = padutils.makeAnimationScheduler( @@ -619,8 +609,6 @@ var paduserlist = (function() rowManager.insertRow(newIndex, userData); } - updateInviteNotice(); - self.updateNumberOfOnlineUsers(); }, updateNumberOfOnlineUsers: function() @@ -668,13 +656,11 @@ var paduserlist = (function() hooks.callAll('userLeave', { userInfo: info }); - updateInviteNotice(); } } }, 8000); // how long to wait userData.leaveTimer = thisLeaveTimer; } - updateInviteNotice(); self.updateNumberOfOnlineUsers(); }, @@ -803,12 +789,13 @@ function closeColorPicker(accept) } colorPickerOpen = false; - $("#mycolorpicker").fadeOut("fast"); + $("#mycolorpicker").removeClass('popup-show'); } function showColorPicker() { previousColorId = myUserInfo.colorId; + $.farbtastic('#colorpicker').setColor(myUserInfo.colorId) if (!colorPickerOpen) { @@ -840,7 +827,7 @@ function showColorPicker() colorPickerSetup = true; } - $("#mycolorpicker").fadeIn(); + $("#mycolorpicker").addClass('popup-show') colorPickerOpen = true; $("#colorpickerswatches li").removeClass('picked'); diff --git a/src/static/js/pluginfw/plugins.js b/src/static/js/pluginfw/plugins.js index ed9c66a37a2..ebb1a0034f0 100644 --- a/src/static/js/pluginfw/plugins.js +++ b/src/static/js/pluginfw/plugins.js @@ -5,6 +5,7 @@ var fs = require("fs"); var tsort = require("./tsort"); var util = require("util"); var _ = require("underscore"); +var settings = require('../../../node/utils/Settings'); var pluginUtils = require('./shared'); @@ -95,7 +96,7 @@ exports.update = async function () { exports.getPackages = async function () { // Load list of installed NPM packages, flatten it to a list, and filter out only packages with names that - var dir = path.resolve(npm.dir, '..'); + var dir = settings.root; let data = await util.promisify(readInstalled)(dir); var packages = {}; diff --git a/src/static/js/scroll.js b/src/static/js/scroll.js index a53dc38c843..46a46c9a6c9 100644 --- a/src/static/js/scroll.js +++ b/src/static/js/scroll.js @@ -5,7 +5,7 @@ Browser Line = each vertical line. A
    can be break into more than one browser line. */ -var caretPosition = require('/caretPosition'); +var caretPosition = require('./caretPosition'); function Scroll(outerWin) { // scroll settings diff --git a/src/static/js/skin_variants.js b/src/static/js/skin_variants.js new file mode 100644 index 00000000000..8fc056acf87 --- /dev/null +++ b/src/static/js/skin_variants.js @@ -0,0 +1,55 @@ +// Specific hash to display the skin variants builder popup +if (window.location.hash.toLowerCase() == "#skinvariantsbuilder") { + $('#skin-variants').addClass('popup-show'); + + $('.skin-variant').change(function() { + updateSkinVariantsClasses(); + }); + + var containers = ['editor', 'background', 'toolbar']; + var colors = ['super-light', 'light', 'dark', 'super-dark']; + + updateCheckboxFromSkinClasses(); + updateSkinVariantsClasses(); + + // add corresponding classes when config change + function updateSkinVariantsClasses() { + var domsToUpdate = [ + $('html'), + $('iframe[name=ace_outer]').contents().find('html'), + $('iframe[name=ace_outer]').contents().find('iframe[name=ace_inner]').contents().find('html') + ]; + colors.forEach(function(color) { + containers.forEach(function(container) { + domsToUpdate.forEach(function(el) { el.removeClass(color + '-' + container); }); + }) + }) + + domsToUpdate.forEach(function(el) { el.removeClass('full-width-editor'); }); + + var new_classes = []; + $('select.skin-variant-color').each(function() { + new_classes.push($(this).val() + "-" + $(this).data('container')); + }) + if ($('#skin-variant-full-width').is(':checked')) new_classes.push("full-width-editor"); + + domsToUpdate.forEach(function(el) { el.addClass(new_classes.join(" ")); }); + + $('#skin-variants-result').val('"skinVariants": "' + new_classes.join(" ") + '",'); + } + + // run on init + function updateCheckboxFromSkinClasses() { + $('html').attr('class').split(' ').forEach(function(classItem) { + var container = classItem.split('-').slice(-1); + + var container = classItem.substring(classItem.lastIndexOf("-") + 1, classItem.length); + if (containers.indexOf(container) > -1) { + var color = classItem.substring(0, classItem.lastIndexOf("-")); + $('.skin-variant-color[data-container="' + container + '"').val(color); + } + }) + + $('#skin-variant-full-width').prop('checked', $('html').hasClass('full-width-editor')); + } +} diff --git a/src/static/js/timeslider.js b/src/static/js/timeslider.js index 3cdff91a951..5ac56bea11a 100644 --- a/src/static/js/timeslider.js +++ b/src/static/js/timeslider.js @@ -165,33 +165,9 @@ function handleClientVars(message) // font family change $("#viewfontmenu").change(function(){ - var font = $("#viewfontmenu").val(); - switch (font) { - case "monospace": setFont("Courier new");break; - case "opendyslexic": setFont("OpenDyslexic");break; - case "comicsans": setFont("Comic Sans MS");break; - case "georgia": setFont("Georgia");break; - case "impact": setFont("Impact");break; - case "lucida": setFont("Lucida");break; - case "lucidasans": setFont("Lucida Sans Unicode");break; - case "palatino": setFont("Palatino Linotype");break; - case "tahoma": setFont("Tahoma");break; - case "timesnewroman": setFont("Times New Roman");break; - case "trebuchet": setFont("Trebuchet MS");break; - case "verdana": setFont("Verdana");break; - case "symbol": setFont("Symbol");break; - case "webdings": setFont("Webdings");break; - case "wingdings": setFont("Wingdings");break; - case "sansserif": setFont("MS Sans Serif");break; - case "serif": setFont("MS Serif");break; - default: setFont("");break; - } + $('#innerdocbody').css("font-family", $(this).val() || ""); }); } -function setFont(font){ - $('#padcontent').css("font-family", font); -} - exports.baseURL = ''; exports.init = init; diff --git a/src/static/js/undomodule.js b/src/static/js/undomodule.js index 6610224fefe..7bb47a62560 100644 --- a/src/static/js/undomodule.js +++ b/src/static/js/undomodule.js @@ -253,7 +253,15 @@ var undoModule = (function() } if (!merged) { - stack.pushEvent(event); + /* + * Push the event on the undo stack only if it exists, and if it's + * not a "clearauthorship". This disallows undoing the removal of the + * authorship colors, but is a necessary stopgap measure against + * https://github.com/ether/etherpad-lite/issues/2802 + */ + if (event && (event.eventType !== "clearauthorship")) { + stack.pushEvent(event); + } } undoPtr = 0; } diff --git a/src/static/js/vendors/nice-select.js b/src/static/js/vendors/nice-select.js new file mode 100644 index 00000000000..cbd978ac7b1 --- /dev/null +++ b/src/static/js/vendors/nice-select.js @@ -0,0 +1,209 @@ +/* jQuery Nice Select - v1.1.0 + https://github.com/hernansartorio/jquery-nice-select + Made by Hernán Sartorio */ + +(function($) { + + $.fn.niceSelect = function(method) { + + // Methods + if (typeof method == 'string') { + if (method == 'update') { + this.each(function() { + var $select = $(this); + var $dropdown = $(this).next('.nice-select'); + var open = $dropdown.hasClass('open'); + + if ($dropdown.length) { + $dropdown.remove(); + create_nice_select($select); + + if (open) { + $select.next().trigger('click'); + } + } + }); + } else if (method == 'destroy') { + this.each(function() { + var $select = $(this); + var $dropdown = $(this).next('.nice-select'); + + if ($dropdown.length) { + $dropdown.remove(); + $select.css('display', ''); + } + }); + if ($('.nice-select').length == 0) { + $(document).off('.nice_select'); + } + } else { + console.log('Method "' + method + '" does not exist.') + } + return this; + } + + // Hide native select + this.hide(); + + // Create custom markup + this.each(function() { + var $select = $(this); + + if (!$select.next().hasClass('nice-select')) { + create_nice_select($select); + } + }); + + function create_nice_select($select) { + $select.after($('
    ') + .addClass('nice-select') + .addClass($select.attr('class') || '') + .addClass($select.attr('disabled') ? 'disabled' : '') + .attr('tabindex', $select.attr('disabled') ? null : '0') + .html('
      ') + ); + + var $dropdown = $select.next(); + var $options = $select.find('option'); + var $selected = $select.find('option:selected'); + + $dropdown.find('.current').html($selected.data('display') || $selected.text()); + + $options.each(function(i) { + var $option = $(this); + var display = $option.data('display'); + + $dropdown.find('ul').append($('
    • ') + .attr('data-value', $option.val()) + .attr('data-display', (display || null)) + .addClass('option' + + ($option.is(':selected') ? ' selected' : '') + + ($option.is(':disabled') ? ' disabled' : '')) + .html($option.text()) + ); + }); + } + + /* Event listeners */ + + // Unbind existing events in case that the plugin has been initialized before + $(document).off('.nice_select'); + + // Open/close + $(document).on('click.nice_select', '.nice-select', function(event) { + var $dropdown = $(this); + + $('.nice-select').not($dropdown).removeClass('open'); + + $dropdown.toggleClass('open'); + + if ($dropdown.hasClass('open')) { + $dropdown.find('.option'); + $dropdown.find('.focus').removeClass('focus'); + $dropdown.find('.selected').addClass('focus'); + if ($dropdown.closest('.toolbar').length > 0) { + $dropdown.find('.list').css('left', $dropdown.offset().left); + $dropdown.find('.list').css('top', $dropdown.offset().top + $dropdown.outerHeight()); + $dropdown.find('.list').css('min-width', $dropdown.outerWidth() + 'px'); + } + + $listHeight = $dropdown.find('.list').outerHeight(); + $top = $dropdown.parent().offset().top; + $bottom = $('body').height() - $top; + $maxListHeight = $bottom - $dropdown.outerHeight() - 20; + if ($maxListHeight < 200) { + $dropdown.addClass('reverse'); + $maxListHeight = 250; + } else { + $dropdown.removeClass('reverse') + } + $dropdown.find('.list').css('max-height', $maxListHeight + 'px'); + + } else { + $dropdown.focus(); + } + }); + + // Close when clicking outside + $(document).on('click.nice_select', function(event) { + if ($(event.target).closest('.nice-select').length === 0) { + $('.nice-select').removeClass('open').find('.option'); + } + }); + + // Option click + $(document).on('click.nice_select', '.nice-select .option:not(.disabled)', function(event) { + var $option = $(this); + var $dropdown = $option.closest('.nice-select'); + + $dropdown.find('.selected').removeClass('selected'); + $option.addClass('selected'); + + var text = $option.data('display') || $option.text(); + $dropdown.find('.current').text(text); + + $dropdown.prev('select').val($option.data('value')).trigger('change'); + }); + + // Keyboard events + $(document).on('keydown.nice_select', '.nice-select', function(event) { + var $dropdown = $(this); + var $focused_option = $($dropdown.find('.focus') || $dropdown.find('.list .option.selected')); + + // Space or Enter + if (event.keyCode == 32 || event.keyCode == 13) { + if ($dropdown.hasClass('open')) { + $focused_option.trigger('click'); + } else { + $dropdown.trigger('click'); + } + return false; + // Down + } else if (event.keyCode == 40) { + if (!$dropdown.hasClass('open')) { + $dropdown.trigger('click'); + } else { + var $next = $focused_option.nextAll('.option:not(.disabled)').first(); + if ($next.length > 0) { + $dropdown.find('.focus').removeClass('focus'); + $next.addClass('focus'); + } + } + return false; + // Up + } else if (event.keyCode == 38) { + if (!$dropdown.hasClass('open')) { + $dropdown.trigger('click'); + } else { + var $prev = $focused_option.prevAll('.option:not(.disabled)').first(); + if ($prev.length > 0) { + $dropdown.find('.focus').removeClass('focus'); + $prev.addClass('focus'); + } + } + return false; + // Esc + } else if (event.keyCode == 27) { + if ($dropdown.hasClass('open')) { + $dropdown.trigger('click'); + } + // Tab + } else if (event.keyCode == 9) { + if ($dropdown.hasClass('open')) { + return false; + } + } + }); + + // Detect CSS pointer-events support, for IE <= 10. From Modernizr. + var style = document.createElement('a').style; + style.cssText = 'pointer-events:auto'; + if (style.pointerEvents !== 'auto') { + $('html').addClass('no-csspointerevents'); + } + + return this; + + }; + +}(jQuery)); \ No newline at end of file diff --git a/src/static/skins/colibris/pad.css b/src/static/skins/colibris/pad.css index ad17132f874..c1cec179c7a 100644 --- a/src/static/skins/colibris/pad.css +++ b/src/static/skins/colibris/pad.css @@ -1,6 +1,8 @@ +@import url("src/general.css"); @import url("src/layout.css"); @import url("src/pad-editor.css"); +@import url("src/components/scrollbars.css"); @import url("src/components/buttons.css"); @import url("src/components/popup.css"); @@ -14,114 +16,60 @@ @import url("src/components/import-export.css"); @import url("src/plugins/brightcolorpicker.css"); -@import url("src/plugins/comments_page.css"); @import url("src/plugins/font_color.css"); -@import url("src/plugins/set_title_on_pad.css"); @import url("src/plugins/tables2.css"); -@import url("src/plugins/embedded_hyperlinks.css"); @import url("src/plugins/author_hover.css"); +@import url("src/plugins/comments.css"); -/* NEUTRAL COLOR */ -body, -#innerdocbody -#users, -#chattext, -#chatinput, -#chatlabel, -#toc, -#tocItems a, -.toolbar ul li a:hover .buttonicon, -.toolbar ul li a, -.toolbar ul li select, -#mycolorpickercancel, -.btn-default, -.color\:black, -[data-color=black], -#chattext.authorColors p, #chattext.authorColors span, -#chattext .time, -#tbl_context_menu ul .yuimenuitemlabel, -.yui-skin-sam .yui-split-button button em:not(.color-picker-button), -#yui-picker-panel .button-group .yui-button:first-child button, -#newComment .sidebar-comment input[type=reset], #newComment .sidebar-comment input[type=reset]:hover, -#newComment .sidebar-comment input[type=submit]:hover, -.suggestion, .comment-reply-input, .reply-suggestion p:not(.reply-comment-suggest-from-p), .comment-text, -.sidebar-comment textarea, .reply-comment-suggest label, .comment-suggest label, .comment-reply-input -#comments, #newComments, .reply-comment-suggest-from-p, -.comment-changeFrom-value, -.comment-changeTo-value, -.reply-suggestion .reply-comment-suggest-from, -.suggestion .comment-suggest-from, -.hyperlink-dialog>.hyperlink-url, -.timeslider #padcontent span , -.exporttype, .timeslider #export > p -{ color: #2E3338 !important; } +@import url("src/pad-variants.css"); -/* MENUS ICONS */ -#edit_title:before, -#tbl-menu:before -{ color: #767676 !important; } -/* MENU BUTTONS */ -.timeslider #editbar .buttontext -{ background-color: #767676 !important; } +/* ----------------------------------------------------------------- + * COLORS + * If you want to change main colors, please replace following CSS variables + * ----------------------------------------------------------------- + */ -/* PRIMARY BUTTONS */ -#mycolorpickersave, -.btn-primary, -#tbl_btn_close, -#save_title button, -#yui-picker-panel .button-group .yui-button:last-child button, -#newComment.sidebar-comment input[type=submit], -.comment-changeTo-approve input[type=submit], -.hyperlink-dialog>.hyperlink-save, -#importsubmitinput, #forcereconnect -{ - background-color: #64d29b; - color: white; -} +:root { + --super-dark-color: #485365; /*#374256;*/ + --dark-color: #576273; /*#4d5d77*/ -/* PRIMARY COLOR */ -h1, -#titlelabel, -.yui-skin-sam .yui-panel .hd, -p[data-l10n-id="ep_comments_page.comment"], -.comment-reply-input-label span, -.stepper, #importmessageabiword, #importmessageabiword > a -{ color: #64d29b; } -#ui-slider-handle, #playpause_button_icon { - background-color: #64d29b; -} -.stepper { - border-color: #64d29b; -} + --primary-color: #64d29b; + --middle-color: #d2d2d2; /* kind of grey, use for border for examples */ + + --light-color: #f2f3f4; /*#f9f9f9;*/ + --super-light-color: white; + + --text-color: var(--super-dark-color); + --text-soft-color: var(--dark-color); + --border-color: var(--middle-color); + --bg-soft-color: var(--light-color); + --bg-color: var(--super-light-color); -/* BACKGROUND COLOR */ -#editorcontainer, #padmain { - background-color: #f9f9f9 !important; + --toolbar-border: none; + + --main-font-family: Quicksand, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; + + --editor-horizontal-padding: 55px; + --editor-vertical-padding: 40px; } +@media (max-width:1000px) { + :root { + --editor-horizontal-padding: 15px; + --editor-vertical-padding: 15px; + } +} -/* NEUTRAL FONT */ -body, -#innerdocbody, -#chatinput, -.toolbar ul li select, -button, input, select, textarea, -td[name=tData], -#comments, #newComments, -#sidediv, -#comments .sidebar-comment, -#timeslider #timer, .exporttype -{ font-family: Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; } +@media (max-width:600px) { + :root { + --editor-horizontal-padding: 15px; + --editor-vertical-padding: 15px; + } +} -/* PRIMARY FONT */ -h1, -#titlelabel, -#chatlabel, -.btn, -.yui-skin-sam .yui-panel .hd, -.reply-suggestion p:not(.reply-comment-suggest-from-p), -p[data-l10n-id="ep_comments_page.comment"], -#newComment.sidebar-comment input[type=submit], -.comment-changeTo-approve input[type=submit], -.hyperlink-dialog>.hyperlink-save -{ font-family: Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif !important; } +/* Default scrollbar values */ +body { + --scrollbar-bg: var(--light-color); + --scrollbar-track: var(--super-light-color); + --scrollbar-thumb: var(--dark-color); +} diff --git a/src/static/skins/colibris/pad.js b/src/static/skins/colibris/pad.js index 88ddce4c38a..1a7bd938a8c 100644 --- a/src/static/skins/colibris/pad.js +++ b/src/static/skins/colibris/pad.js @@ -1,4 +1,6 @@ function customStart() { $('#pad_title').show(); + $('.buttonicon').mousedown(function() { $(this).parent().addClass('pressed'); }) + $('.buttonicon').mouseup(function() { $(this).parent().removeClass('pressed'); }) } diff --git a/src/static/skins/colibris/src/components/buttons.css b/src/static/skins/colibris/src/components/buttons.css index 93879023ec8..ccaea9d4d9a 100644 --- a/src/static/skins/colibris/src/components/buttons.css +++ b/src/static/skins/colibris/src/components/buttons.css @@ -1,21 +1,31 @@ -.btn, #mycolorpickercancel, #mycolorpickersave, #save_title button, #yui-picker-panel .button-group .yui-button button, .hyperlink-dialog>.hyperlink-save, .timeslider #editbar .buttontext, -#importsubmitinput, #forcereconnect +button, .btn { - margin-right: 10px; padding: 5px 20px; border-radius: 4px; - font-size: 13px; line-height: 1.5; width: auto; - border: none !important; + border: none; font-weight: bold; text-transform: uppercase; position: relative; background: none; - top: 0; - left: 0; + cursor: pointer; } -.btn:hover, #mycolorpickercancel:hover, #mycolorpickersave:hover, #save_title button:hover, .hyperlink-dialog>.hyperlink-save:hover, #importsubmitinput:hover, #forcereconnect:hover { - cursor: pointer; +.btn-primary +{ + background-color: #64d29b; + background-color: var(--primary-color); + color: #ffffff; + color: var(--bg-color); +} +.btn-default { + color: #485365; + color: var(--text-color); } + +.buttonicon:before, [class^="buttonicon-"]:before, [class*=" buttonicon-"]:before { + line-height: 18px; +} + + diff --git a/src/static/skins/colibris/src/components/chat.css b/src/static/skins/colibris/src/components/chat.css index 7a2979e02c1..61d992c5f21 100644 --- a/src/static/skins/colibris/src/components/chat.css +++ b/src/static/skins/colibris/src/components/chat.css @@ -1,33 +1,43 @@ #chatbox { + background-color: transparent !important; + color: var(--text-color); +} +.chat-content { background: none; padding: 0; - background-color: white; - border: none; - box-shadow: 0 0 0 1px rgba(99, 114, 130, 0.16), 0 8px 16px rgba(27, 39, 51, 0.08); width: 400px; height: 300px; - background-color: #f9f9f9 !important; + background-color: #f2f3f4; + background-color: var(--bg-soft-color); } -#chatbox.stickyChat { - width: 193px !important; - border: none !important; +.chat-content, #chaticon { + box-shadow: 0 0 0 1px rgba(99, 114, 130, 0.16), 0 8px 16px rgba(27, 39, 51, 0.08); + border: none; } -#chatbox.stickyChat.chatAndUsersChat{ - margin-top: 181px; +#chaticon { + padding: 10px 20px; + background-color: #f2f3f4; + background-color: var(--bg-soft-color); + color: #485365; + color: var(--text-color); + right: 30px; +} + +#chatbox.stickyChat .chat-content { + border: none; box-shadow: none; - border-top: 1px solid #d2d2d2 !important; - padding: 0!important; + background-color: #f2f3f4; + background-color: var(--bg-soft-color); } #titlebar { bottom: 0; - line-height: 39px; + line-height: 44px; height: 44px; padding: 0 7px; z-index: 20000; - border-bottom: 1px solid #d2d2d2; } #titlelabel, #chatlabel { @@ -35,80 +45,40 @@ font-weight: bold; } -#titlelabel { font-size: 16px; } +#titlebar #titlelabel { font-size: 16px; } #chatlabel { margin-right: 15px; } #chattext { - top: 45px; - font-size: 13px; - bottom: 52px; - overflow-y: auto; padding: 0; - border: none; - border-bottom: 1px solid #cccccc; -} - -.plugin-ep_author_neat #chattext { - padding: 10px; -} - -.plugin-ep_author_neat #chattext.authorColors p, -.plugin-ep_author_neat #chattext.authorColors span { - background-color: transparent !important; -} - -#chattext p b { - color: #4c4c4c; + border-top: 1px solid #ffffff; + border-top: 1px solid var(--bg-color); + border-bottom: 1px solid #ffffff; + border-bottom: 1px solid var(--bg-color); + background-color: inherit; + color: inherit; } - -#chattext::-webkit-scrollbar-track { - background-color: #f6f6f6; - border: 1px solid #f0f0f0; +#chattext p { + padding: 4px 10px; } - -#chattext::-webkit-scrollbar { - width: 7px; -} - -#chattext::-webkit-scrollbar-thumb { - border-radius: 10px; - background-color: #C5C5C5; +#chattext:not(.authorColors) p:first-child { + padding-top: 10px; } - -#chatbox.stickyChat #chattext { - padding: 0px; +#chattext:not(.authorColors) p:last-child { + padding-bottom: 10px; } #chatinputbox { padding: 8px; } - -#chatinput { - width: calc(100% - 20px); - float: right; -} - -.plugin-ep_author_neat #chatbox.stickyChat #chattext { - padding: 5px 3px; -} - -#chaticon { - box-shadow: 0 0 0 1px rgba(99, 114, 130, 0.16), 0 8px 16px rgba(27, 39, 51, 0.08); - border: none; - padding: 10px 20px; - right: 30px; +#chatinputbox #chatinput { + background-color: #ffffff; + background-color: var(--bg-color); } @media (max-width: 720px) { #chaticon { right: 0; - bottom: 44px; - } - - #chatbox { - width: 100%; - right: 0; } - #titlesticky { display: none; } + .stick-to-screen-btn { display: none; } } \ No newline at end of file diff --git a/src/static/skins/colibris/src/components/form.css b/src/static/skins/colibris/src/components/form.css index 5d34fc865d3..aa82218c2af 100644 --- a/src/static/skins/colibris/src/components/form.css +++ b/src/static/skins/colibris/src/components/form.css @@ -1,9 +1,114 @@ -#input_title, #chatinput, .hyperlink-dialog>.hyperlink-url { - border: 1px solid #d2d2d2; - height: 18px; +input[type="text"], select, textarea, .nice-select { border-radius: 3px; + box-shadow: none; + border: none; + outline: 0; +} + +input[type="text"], textarea { padding: 8px 10px; - background: none !important; - background-color: white !important; - box-shadow: none !important; -} \ No newline at end of file + background-color: #f2f3f4; + background-color: var(--bg-soft-color); + border: none; + color: #485365; + color: var(--text-color); +} +input[type="text"]::placeholder, textarea::placeholder { + color: #576273; + color: var(--text-soft-color); +} +select, .nice-select { + background-color: #f2f3f4; + background-color: var(--bg-soft-color); + border: none; + padding: 4px 10px; + padding-right: 25px; + font-weight: bold; + line-height: inherit; +} +.nice-select .list { + background-color: #f2f3f4; + background-color: var(--bg-soft-color); +} +.nice-select .option:hover,.nice-select .option.focus,.nice-select .option.selected.focus { + background-color: #ffffff; + background-color: var(--bg-color); +} +.nice-select .option { + padding: 0 15px; +} +.popup .nice-select .list { + right: 0; + left: auto; +} + + +/* Checkboxes + ========================================================================== */ +/* Remove default checkbox */ +[type="checkbox"]:not(:checked), +[type="checkbox"]:checked { + position: absolute; + opacity: 0; + pointer-events: none; +} + +[type="checkbox"] + label { + position: relative; + padding-left: 2.5rem; + cursor: pointer; + display: inline-block; + height: 1.4rem; + line-height: 1.4rem; + font-size: 1rem; +} + +[type="checkbox"] + label:before, +[type="checkbox"] + label:after { + content: ''; + position: absolute; + margin-top: 4px; + transition: all .2s ease-in-out; +} + +/* BEFORE, the container*/ +[type="checkbox"] + label:before { + width: 24px; + height: 14px; + top: 0; + left: 0; + border-radius: 6px; + border: 2px solid #576273; + border: 2px solid var(--text-soft-color); + background-color: #f2f3f4; + background-color: var(--bg-soft-color); + opacity: .7; +} +[type="checkbox"]:checked + label:before { + background-color: transparent; + border-color: #64d29b; + border-color: var(--primary-color); +} + +/* AFTER, the circle moving */ +[type="checkbox"] + label:after { + width: 16px; + height: 16px; + border-radius: 50%; + background-color: #576273; + background-color: var(--text-soft-color); + top: -1px; + left: -3px; +} +[type="checkbox"]:checked + label:after { + background-color: #64d29b; + background-color: var(--primary-color); + transform: translateX(14px); +} + +[type="checkbox"]:checked:disabled + label, +[type="checkbox"]:checked:disabled + label:before, +[type="checkbox"]:checked:disabled + label:after { + cursor: not-allowed; + opacity: .4; +} diff --git a/src/static/skins/colibris/src/components/gritter.css b/src/static/skins/colibris/src/components/gritter.css index 7c514010c64..fa255fe4a22 100644 --- a/src/static/skins/colibris/src/components/gritter.css +++ b/src/static/skins/colibris/src/components/gritter.css @@ -1,28 +1,65 @@ -/* Popups at the bottom of the page to indicate when the pad expires, and others stuff */ +.gritter-item:not(.error) .popup-content{ + background-color: #64d29b; + background-color: var(--primary-color); + color: #ffffff; + color: var(--bg-color); +} +.gritter-item .popup-content { + padding: 15px; + box-shadow: 0 0 0 1px rgba(99, 114, 130, 0.16), 0 8px 16px rgba(27, 39, 51, 0.08); +} +#gritter-container.bottom .gritter-item .popup-content { + margin-top: 10px; +} +#gritter-container.top .gritter-item .popup-content { + margin-bottom: 10px; +} +.gritter-item p { + margin: 0 !important; +} +.gritter-item .gritter-title { + margin-bottom: 10px; +} +.gritter-item .gritter-close { + margin-left: 15px; + margin-right: 0px; +} +.gritter-item:not(.error) .gritter-close .buttonicon { + color: #ffffff; + color: var(--bg-color); +} -.gritter-title { - text-shadow: none; +/* CHAT GRIITER ITEM */ +.gritter-item.chat-gritter-msg:not(.error) .popup-content { + background-color: white; + background-color: var(--bg-color); + color: #485365; + color: var(--text-color); +} +.gritter-item.chat-gritter-msg .gritter-content { + text-align: left; +} +.gritter-item.chat-gritter-msg .author-name { + font-weight: bold; + margin-right: 5px; +} +.gritter-item.chat-gritter-msg:not(.error) .gritter-close .buttonicon { + color: #485365; + color: var(--text-color); } -#gritter-notice-wrapper { - background-color: #fff; - box-shadow: 0 0 0 1px rgba(99, 114, 130, 0.16), 0 8px 16px rgba(27, 39, 51, 0.08); - border-radius: 3px; - padding: 15px 20px 5px 30px; - bottom: 50px !important; - right: 30px !important; +.gritter-item.saved-revision { + max-width: 600px; } -@media (max-width: 1100px) { - #gritter-notice-wrapper { - display: none; - } +#gritter-container.top .gritter-item.popup > .popup-content { + transform: scale(0.8) translateY(-100px); +} +#gritter-container.bottom .gritter-item.popup > .popup-content { + transform: scale(0.8) translateY(0px); } -.gritter-item { - font-family: Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif !important; - color: #4e545b; - font-size: 12px; - line-height: 20px; - padding: 0; +.gritter-item.popup.popup-show > .popup-content { + transform: scale(1) translateY(0) !important; + transition: all 0.4s cubic-bezier(0.74, -0.05, 0.27, 1.75) !important; } \ No newline at end of file diff --git a/src/static/skins/colibris/src/components/import-export.css b/src/static/skins/colibris/src/components/import-export.css index bdaa184e9c2..d8425d89529 100644 --- a/src/static/skins/colibris/src/components/import-export.css +++ b/src/static/skins/colibris/src/components/import-export.css @@ -1,32 +1,16 @@ -#exportColumn { - margin-top: 0; - padding-left: 20px; - width: calc(50% - 20px); -} - #importmessageabiword { font-style: italic; - font-size: 13px; + color: #64d29b; + color: var(--primary-color); } #importmessageabiword > a { font-weight: bold; text-decoration: underline; -} - -.exportlink { - font-size: 14px; - margin: 0; - margin-bottom: 7px; - margin-left: 10px; -} - -.exporttype { - margin-left: 5px; - font-size: 14px; + color: #64d29b; + color: var(--primary-color); } #importmessagefail { - font-size: 13px; margin-top: 10px; } diff --git a/src/static/skins/colibris/src/components/popup.css b/src/static/skins/colibris/src/components/popup.css index 7b3c0381b7a..0a50c9bbe15 100644 --- a/src/static/skins/colibris/src/components/popup.css +++ b/src/static/skins/colibris/src/components/popup.css @@ -1,30 +1,70 @@ -#users, -#mycolorpicker, -.popup, -.hyperlink-dialog { - border-radius: 3px; - padding: 20px 20px; +.popup-content { + border-radius: 5px; + padding: 25px; background: none; - background-color: white; + background-color: #ffffff; + background-color: var(--bg-color); + color: #576273; + color: var(--text-soft-color); border: none; box-shadow: 0 0 0 1px rgba(99, 114, 130, 0.16), 0 8px 16px rgba(27, 39, 51, 0.08); } -#users input[type=text], -.popup input[type=text] { - border: none !important; - border-bottom: 1px solid #d7d8da !important; +#mycolorpicker, #users { + min-width: 0; } .popup h1 { - margin-bottom: 15px; + margin-bottom: 20px; + font-size: 1.6rem; } .popup h2 { margin-bottom: 15px; + margin-top: 20px; + color: #485365; + color: var(--text-color); } -.popup p { +.popup:not(.comment-modal) p { margin: 10px 0; } +.popup .dropdowns-container .dropdown-line { + margin-top: 15px; +} +.popup .dropdowns-container label { + width: 120px; + display: inline-block; +} +.popup .dropdowns-container .nice-select { + min-width: 180px; +} + +@media (max-width: 720px) { + .popup-content { + padding: 1rem; + box-shadow: 0 0 0 1px rgba(99, 114, 130, 0.16), -1px 1px 16px 3px rgba(27, 39, 51, 0.12); + } + .popup .dropdowns-container select { + min-width: 0; + } +} + +/* SKIN Variants Popup */ +#skin-variants { + bottom: 0; + left: 0; + right: auto; + top: auto; +} +#skin-variants .popup-content > p { + margin-top: 25px; +} +#skin-variants-result{ + background-color: #f2f3f4; + background-color: var(--bg-soft-color); +} +.skin-variant-container { + text-transform: capitalize; +} diff --git a/src/static/skins/colibris/src/components/scrollbars.css b/src/static/skins/colibris/src/components/scrollbars.css new file mode 100644 index 00000000000..cd4ea08b59a --- /dev/null +++ b/src/static/skins/colibris/src/components/scrollbars.css @@ -0,0 +1,39 @@ +@media (min-width: 721px) { + ::-webkit-scrollbar-track { + background-color: white; + background-color: var(--scrollbar-track); + border-radius: 10px; + border: 7px solid #f2f3f4; + border: 7px solid var(--scrollbar-bg); + } + + ::-webkit-scrollbar { + width: 22px; + } + + ::-webkit-scrollbar-thumb { + border-radius: 10px; + background-color: #576273; + background-color: var(--scrollbar-thumb); + border: 7px solid #f2f3f4; + border: 7px solid var(--scrollbar-bg); + } +} + +.thin-scrollbar::-webkit-scrollbar-track { + background-color: #f2f3f4; + background-color: var(--bg-soft-color); + border-radius: 0px; + border: none; +} + +.thin-scrollbar::-webkit-scrollbar { + width: 6px; +} + +.thin-scrollbar::-webkit-scrollbar-thumb { + border-radius: 0px; + background-color: #d2d2d2; + background-color: var(--middle-color); + border: none; +} \ No newline at end of file diff --git a/src/static/skins/colibris/src/components/sidediv.css b/src/static/skins/colibris/src/components/sidediv.css index 2fb8377476f..63eee2dd526 100644 --- a/src/static/skins/colibris/src/components/sidediv.css +++ b/src/static/skins/colibris/src/components/sidediv.css @@ -1,14 +1,16 @@ #sidediv { background-color: transparent; border: none; + opacity: .8; } #sidedivinner>div:before { - font-size: 13px; + font-family: var(--main-font-family); /* the parent div have font-family monospace (line number) */ + color: #485365; + color: var(--text-color); padding-right: 18px !important; - color: #6a6a6b; - text-transform: uppercase; - font-size: 11px !important; + text-transform: capitalize; + font-size: 12px !important; font-weight: bold; } @@ -21,8 +23,10 @@ #sidedivinner>div { line-height: 24px; - font-size: 10px !important; - color: #a0a0a0; + font-size: 9px !important; + font-family: RobotoMono; + color: #576273; + color: var(--text-soft-color); } #sidedivinner.authorColors>div, #sidedivinner.authorColors>div.primary-none, #sidedivinner>div { diff --git a/src/static/skins/colibris/src/components/table-of-content.css b/src/static/skins/colibris/src/components/table-of-content.css index b2f26c4a220..fd6c5ea2bef 100644 --- a/src/static/skins/colibris/src/components/table-of-content.css +++ b/src/static/skins/colibris/src/components/table-of-content.css @@ -1,11 +1,21 @@ #toc { - background: none !important; - background-color: rgb(249, 249, 249) !important; - padding: 20px !important; - width: 146px !important; - padding-left: 15px !important; + padding: 20px 20px 10px 10px !important; + min-width: 146px !important; + background-color: transparent !important; + border: none !important; + order: -2; } #tocItems { line-height: 40px !important; +} + +.plugin-ep_resizable_bars #toc { + min-width: 186px !important; +} + +@media (max-width: 1200px) { + #toc { + padding-top: 10px !important + } } \ No newline at end of file diff --git a/src/static/skins/colibris/src/components/toolbar.css b/src/static/skins/colibris/src/components/toolbar.css index 78d774c3083..354e1324965 100644 --- a/src/static/skins/colibris/src/components/toolbar.css +++ b/src/static/skins/colibris/src/components/toolbar.css @@ -1,26 +1,50 @@ .toolbar { - height: 39px !important; - padding-top: 0; - margin: 0; - background-color: white !important; - background: none; - border: 1px solid #d2d2d2 + border-bottom: none; + padding: 0; + background-color: #ffffff; + background-color: var(--bg-color); + color: #576273; + color: var(--text-soft-color); + border-bottom: none; +} + +#editbar.editor-scrolled { + border-bottom: 1px solid #d2d2d2; + border-bottom: var(--toolbar-border); +} + +.toolbar ul { + align-items: center; +} + +.toolbar ul.menu_left { + padding-left: 5px; +} + +.toolbar ul li { + margin: 7px 1px; +} + +.toolbar ul li a, .toolbar .buttonicon { + color: inherit; } .toolbar .buttonicon { background-color: transparent; - font-size: 14px; - color: #767676; + font-size: 15px; +} +.buttonicon-insertorderedlist:before, +.buttonicon-insertunorderedlist:before, +.buttonicon-indent:before, +.buttonicon-outdent:before { + font-size: 16px !important; } .toolbar ul li.separator { - padding: 0; - visibility: visible; + visibility: hidden; width: 1px; margin: 0 10px; - margin-right: 6px; - height: 39px; - background-color: rgba(78, 85, 92, 0.22); + position: relative; } .toolbar.condensed ul li { @@ -35,111 +59,95 @@ background-color: transparent; background: none; border: none; - margin-top: 6px; + border-radius: 3px !important; + transition: background-color .1s; } -.toolbar ul li a:hover, -.toolbar ul li a.selected, -.toolbar ul li a:focus { - background: none !important; - border-radius: 0; +.toolbar ul li a:hover, .toolbar ul li select:hover { + background-color: #f2f3f4; + background-color: var(--bg-soft-color); + color: #485365; + color: var(--text-color); } - -.toolbar ul li a:hover { - background:#f7f7f7!important +.toolbar ul li a.selected { + background-color: #f2f3f4; + background-color: var(--bg-soft-color); } - -.toolbar ul li a.selected, -.toolbar ul li a:focus { - background: #eaeaea!important; +.toolbar ul li a.pressed, +.toolbar ul li select:active { + color: #64d29b; + color: var(--primary-color); } -.toolbar ul li select { - border: none; - border-bottom: 1px solid #d7d8da; - border-radius: 0; - width: 90px; - margin-top: 5px; +.toolbar ul li select:active option { + background-color: #ffffff; + background-color: var(--bg-color); + color: #576273; + color: var(--text-soft-color); + padding: 5px; } -.toolbar ul { - height: 39px; +.toolbar .menu_right li a.selected { + background-color: #576273; + background-color: var(--text-soft-color); + color: #ffffff; + color: var(--bg-color); } -.toolbar ul.menu_left { - left: 8px; +.toolbar ul li[data-key=showusers] { + margin: 0; + margin-left: 15px; + width: 45px; + height: 100%; +} +.toolbar ul li[data-key=showusers] > a { + width: 100%; + height: 100%; + border-radius: 0 !important; } -.toolbar ul.menu_right { - right: 0; - padding: 0; +.toolbar .menu_right .separator { + display: none; +} +.toolbar .menu_right li { + margin-left: 10px; } -.toolbar ul li[data-key=showusers] a { - margin: 0; - height: 59px; - line-height: 25px; - width: 45px; - margin-left: -10px; - border-radius: 0; +.toolbar.cropped .menu_left { + height: 39px; + padding-top: 1px; +} +.toolbar .show-more-icon-btn { + font-size: 1.8rem; + color: #64d29b; + color: var(--primary-color); } @media (max-width: 1000px) { .toolbar ul li.separator { - margin: 0 2px; + margin: 0 5px; background: none; display: block; } - - .toolbar ul li[data-key=showusers] a { - margin-left: 0 !important; - } } @media (max-width: 720px) { -.toolbar ul { - height: 39px; - background: none; - background-color: transparent; - border: none !important; - padding: 0 !important; - overflow-x: visible; - } - .toolbar ul.menu_left { - padding-top: 2px !important; - } - .toolbar ul.menu_right { - left: 0; - padding-left: 8px !important; - padding-top: 8px !important; - height: 35px !important; - border-top: 1px solid #d2d2d2 !important; - background-color: white; - } - .toolbar ul li a { - padding: 4px 5px !important; - } - .toolbar ul li[data-key=showusers] { - position: absolute; - right: 0; - top: 0; + .toolbar ul li { + margin: 5px 2px; } - .toolbar ul li[data-key=showusers] a { - padding-top: 9px !important; - } - .toolbar ul li a:hover { background-color: transparent; } - - #connectivity, #embed, #import_export, #settings { bottom: 42px; } - li.superscript, - li.subscript, - li[data-key="undo"], - li[data-key="redo"] { - display: none; + .toolbar .menu_right { + border-top: 1px solid #d2d2d2; + border-top: var(--toolbar-border); + background-color: #ffffff; + background-color: var(--bg-color); + padding: 0; } - .toolbar ul li.separator { margin: 0; } + .toolbar ul li a:hover { background-color: transparent; } + + .toolbar ul li.separator { margin: 0; display: none; } } diff --git a/src/static/skins/colibris/src/components/users.css b/src/static/skins/colibris/src/components/users.css index bb5fbb49500..beb498e3b2d 100644 --- a/src/static/skins/colibris/src/components/users.css +++ b/src/static/skins/colibris/src/components/users.css @@ -1,5 +1,18 @@ table#otheruserstable { - margin-top: 10px !important; + margin-top: 20px; +} + +.popup#users.chatAndUsers > .popup-content { + padding: 20px 10px; + height: 250px; + border-left: none; + transition: none; + border-bottom-color: #d2d2d2; + border-bottom-color: var(--border-color); +} +.popup#users.chatAndUsers #mycolorpicker.popup { + right: calc(100% + 30px); + top: 15px; } #otheruserstable .swatch { @@ -16,80 +29,24 @@ table#otheruserstable { margin-left: 35px; } -#myusernameedit { - width: 110px; -} - -#myswatchbox { - background: none; - float: left; - position: relative; - left: 0; - top: 0; +input#myusernameedit { + min-width: 110px; border: none !important; + background-color: transparent !important; + border-bottom: 1px solid #d2d2d2 !important; + border-bottom: 1px solid var(--border-color) !important; + border-radius: 0; + padding-bottom: 5px; } #myswatch { border-radius: 50%; } -#nootherusers { - padding: 0; -} - -#mycolorpicker { - width: auto; - height: auto; - left: -280px; -} - #colorpicker { margin-bottom: 25px; } -#mycolorpickercancel { - padding-left: 3px; -} - -#mycolorpickersave { - color: #fff; -} - #mycolorpickerpreview { - float: right; - top: 0; - left: 0; - position: relative; border-radius: 50%; - height: 20px; - width: 20px; -} - -@media (max-width: 720px) { - #users { - bottom: 42px; - top: initial !important; - height: auto !important; - } - - #mycolorpicker { - width: auto; - height: auto; - right: 0; - bottom: 42px; - left: initial; - top: initial !important; - } -} - -#users.chatAndUsers { - width: 172px!important; - box-shadow: none; - border: none !important; - padding: 10px; - padding-top: 15px; -} - -#users.chatAndUsers #myusernameedit { - width: calc(100% - 10px); } \ No newline at end of file diff --git a/src/static/skins/colibris/src/general.css b/src/static/skins/colibris/src/general.css new file mode 100644 index 00000000000..f51d46ce5aa --- /dev/null +++ b/src/static/skins/colibris/src/general.css @@ -0,0 +1,15 @@ +html { + font-size: 15px; +} + +body { + color: #485365; + color: var(--text-color); + font-family: Quicksand, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; + font-family: var(--main-font-family); +} + +h1 { + color: #64d29b; + color: var(--primary-color); +} \ No newline at end of file diff --git a/src/static/skins/colibris/src/layout.css b/src/static/skins/colibris/src/layout.css index 9a32962cf09..a6dd784d7c5 100644 --- a/src/static/skins/colibris/src/layout.css +++ b/src/static/skins/colibris/src/layout.css @@ -1,76 +1,48 @@ -#connectivity, -#embed, -#import_export, -#settings, -#users { - top: 38px; - right: 30px; -} - -#editorcontainer { - top: 41px !important; - padding-top: 0 !important; -} - -#outerdocbody, .timeslider #editorcontainerbox { - max-width: 900px; +#outerdocbody { margin: 0 auto; padding-top: 20px; + width: 100%; } -#outerdocbody { - overflow-y: auto; - position: relative; - background-color: transparent; - padding-left: 40px; /* space for side div */ +#editorcontainerbox { + background-color: #f2f3f4; + background-color: var(--bg-color); } -#outerdocbody.plugin-ep_author_neat { - padding-left: 120px; /* more space for sidediv */ -} -@media (max-width:600px) { - #outerdocbody.plugin-ep_author_neat { padding-left: 0; } - #options-linenoscheck { display:none; } - #options-linenoscheck ~ label { display:none; } +#editorcontainerbox .sticky-container { + width: 250px; } #outerdocbody.sidediv-hidden { padding-left: 0; /* sidediv hidden */ } -#outerdocbody iframe { - display: block; - position: relative; - left: 0 !important; - top: 0; -} - -#outerdocbody iframe, .timeslider #editorcontainerbox { - padding: 55px; - box-shadow: 0 0 0 0.5px rgba(209, 209, 209, 0.32), 0 0 7pt 0pt rgba(204, 204, 204, 0.52); +#outerdocbody iframe, #outerdocbody > #innerdocbody { + max-width: 900px; + padding: 40px 55px; + padding-left: var(--editor-horizontal-padding); + padding-right: var(--editor-horizontal-padding); + padding-top: var(--editor-vertical-padding); + padding-bottom: var(--editor-vertical-padding); + box-shadow: none; border: 0; - border-radius: 5px; - background-color: white; - width: calc(100% - 110px) !important; /* 100% - padding */ + border-radius: 8px 8px 0 0; + background-color: #ffffff; + background-color: var(--bg-color); + color: #485365; + color: var(--text-color); } - #sidediv { - position: absolute; - right: calc(100% - 35px); - left: initial; - top: 74px !important; - padding: 0; + /* Padding must be the same than editor, otherwise it creates problem */ + padding-top: 40px; /* = #innerdocbody iframe vertical padding */ + padding-bottom: 40px; + padding-top: var(--editor-vertical-padding); + padding-bottom: var(--editor-vertical-padding); } -#outerdocbody.plugin-ep_author_neat #sidediv { - right: calc(100% - 113px); -} - -/* Fixs comments_page & author_hover does not take in account the document padding */ -.comment-modal { margin-top: 75px !important; margin-left: 45px; } +/* Fixs author_hover does not take in account the document padding */ .authortooltip { margin-top: 65px !important; margin-left: 60px; } .caretindicator { margin-top: 61px!important; margin-left: 52px; } - #outerdocbody.plugin-ep_author_neat .authortooltip{ margin-left: 145px; } #outerdocbody.plugin-ep_author_neat .caretindicator{ margin-left: 52px; margin-top: 65px!important;} @media (max-width:1000px) { @@ -79,33 +51,16 @@ #outerdocbody.plugin-ep_author_neat .caretindicator{ margin-left: 17px; } } -@media (min-width: 1381px) { - #outerdocbody.plugin-ep_comments_page { padding-right: 150px; } } - #outerdocbody.plugin-ep_comments_page #comments { left: calc(100% - 150px) } -@media (max-width: 1380px) { - #outerdocbody.plugin-ep_comments_page #comments { left: calc(100% - 220px) } - #outerdocbody.plugin-ep_comments_page { padding-right: 220px; } -} -@media (max-width: 1278px) { - #outerdocbody.plugin-ep_comments_page #comments { display: none; } - #outerdocbody.plugin-ep_comments_page { padding-right: 0px; } -} - @media (max-width:1000px) { #outerdocbody { - max-width: none; padding-top: 0; } - #outerdocbody iframe, .timeslider #editorcontainerbox { - padding: 20px !important; + #outerdocbody iframe, #outerdocbody > #innerdocbody { + max-width: none; border-radius: 0; - width: calc(100% - 40px) !important; /* 100% - padding */ - } - #sidediv { - top: 20px !important; /* = #outerdocbody iframe padding-top */ } - .comment-modal, .authortooltip { margin-top: 20px !important; } + .authortooltip { margin-top: 20px !important; } .caretindicator { margin-top: 0px !important; } #outerdocbody.plugin-ep_author_neat .caretindicator { margin-top: 10px !important; } @@ -116,18 +71,9 @@ #outerdocbody.plugin-ep_author_neat #sidediv { padding-right: 0 !important; } } -@media (max-width:600px) { - html { overflow: scroll; } - #outerdocbody { - width: 100%; - } - #outerdocbody iframe, .timeslider #editorcontainerbox { - padding: 15px !important; - width: calc(100% - 30px) !important; /* 100% - padding */ - } - #sidediv { - display: none; - top: 15px !important; /* = #outerdocbody iframe padding-top */ +@media only screen and (max-width: 720px) { + #editorcontainerbox { + margin-bottom: 39px; /* margin for bottom toolbar */ } } diff --git a/src/static/skins/colibris/src/pad-editor.css b/src/static/skins/colibris/src/pad-editor.css index aae79bf844c..1d50ed0f9c9 100644 --- a/src/static/skins/colibris/src/pad-editor.css +++ b/src/static/skins/colibris/src/pad-editor.css @@ -1,43 +1,34 @@ -#innerdocbody, #padcontent { +#innerdocbody { font-size: 15px; line-height: 25px; padding: 0; + background: transparent; + color: #485365; + color: var(--text-color); } -#innerdocbody span, #padcontent span { +#innerdocbody span, #innerdocbody span { padding: 4px 0 !important; } -#innerdocbody h1 span, #padcontent h1 span { +#innerdocbody h1 span, #innerdocbody h1 span { padding: 0; } -body { - overflow: hidden; -} - option { text-transform: capitalize; } -h1 { +#innerdocbody h1 { font-size: 2.5em !important; } -h3 { +#innerdocbody h3 { font-size: 1.15em; letter-spacing: 1px; } -a { - color: #3f51b5; -} - -h1, h2, h3, h4, h5, h6 { - line-height: 120%; -} - - - - - +#innerdocbody a { + color: #64d29b; + color: var(--primary-color); +} \ No newline at end of file diff --git a/src/static/skins/colibris/src/pad-variants.css b/src/static/skins/colibris/src/pad-variants.css new file mode 100644 index 00000000000..212acdfcf9d --- /dev/null +++ b/src/static/skins/colibris/src/pad-variants.css @@ -0,0 +1,228 @@ +/* =========================== */ +/* === Super Light Toolbar === */ +/* =========================== */ +.super-light-toolbar .toolbar, .super-light-toolbar .popup-content { + --text-color: var(--super-dark-color); + --text-soft-color: var(--dark-color); + --border-color: #e4e6e9; + --bg-soft-color: var(--light-color); + --bg-color: var(--super-light-color); +} +/* ===================== */ +/* === Light Toolbar === */ +/* ===================== */ +.light-toolbar .toolbar, .light-toolbar .popup-content { + --text-color: var(--super-dark-color); + --text-soft-color: var(--dark-color); + --border-color: var(--middle-color); + --bg-soft-color: var(--super-light-color); + --bg-color: var(--light-color); +} +/* ========================== */ +/* === Super Dark Toolbar === */ +/* ========================== */ +.super-dark-toolbar .toolbar, .super-dark-toolbar .popup-content { + --text-color: var(--super-light-color); + --text-soft-color: var(--light-color); + --border-color: var(--dark-color); + --bg-soft-color: var(--dark-color); + --bg-color: var(--super-dark-color); +} +.super-dark-toolbar.super-dark-editor .popup-content { + border: 1px solid var(--dark-color); + box-shadow: none; +} +/* ==================== */ +/* === Dark Toolbar === */ +/* ==================== */ +.dark-toolbar .toolbar, .dark-toolbar .popup-content { + --text-color: var(--super-light-color); + --text-soft-color: var(--light-color); + --border-color: var(--super-dark-color); + --bg-soft-color: var(--super-dark-color); + --bg-color: var(--dark-color); +} + + + + + +/* ============================ */ +/* == Super Light Background == */ +/* ============================ */ +.super-light-background #editorcontainerbox, .super-light-background #sidediv, +.super-light-background #chatbox, .super-light-background #outerdocbody, .super-light-background { + --text-color: var(--super-dark-color); + --text-soft-color: var(--dark-color); + --border-color: #e4e6e9; + --bg-soft-color: var(--light-color); + --bg-color: var(--super-light-color); +} +.super-light-background body, .full-width-editor.super-light-editor body:not(.comments-active) { + --scrollbar-bg: var(--super-light-color); + --scrollbar-track: var(--light-color); + --scrollbar-thumb: var(--dark-color); +} +.super-light-background .compact-display-content { + background-color: var(--super-light-color); +} +/* ====================== */ +/* == Light Background == */ +/* ====================== */ +.light-background #editorcontainerbox, .light-background #sidediv, +.light-background #chatbox, .light-background #outerdocbody, .light-background { + --text-color: var(--super-dark-color); + --text-soft-color: var(--dark-color); + --border-color: var(--middle-color); + --bg-soft-color: var(--super-light-color); + --bg-color: var(--light-color); +} +.light-background body, .full-width-editor.light-editor body:not(.comments-active) { + --scrollbar-bg: var(--light-color); + --scrollbar-track: var(--super-light-color); + --scrollbar-thumb: var(--dark-color); +} +.light-background .compact-display-content { + background-color: var(--light-color); +} +/* =========================== */ +/* == Super Dark Background == */ +/* =========================== */ +.super-dark-background #editorcontainerbox, .super-dark-background #sidediv, +.super-dark-background #chatbox, .super-dark-background #outerdocbody, .super-dark-background { + --text-color: var(--super-light-color); + --text-soft-color: var(--light-color); + --border-color: var(--dark-color); + --bg-soft-color: var(--dark-color); + --bg-color: var(--super-dark-color); +} +.super-dark-background body, .full-width-editor.super-dark-editor body:not(.comments-active) { + --scrollbar-bg: var(--super-dark-color); + --scrollbar-track: var(--dark-color); + --scrollbar-thumb: var(--light-color); +} +.super-dark-background .compact-display-content { + background-color: var(--super-dark-color); +} +/* Special combinaison with toolbar */ +.super-dark-background.super-dark-toolbar .popup-content { + border: 1px solid var(--dark-color); + box-shadow: none; +} +/* ===================== */ +/* == Dark Background == */ +/* ===================== */ +.dark-background #editorcontainerbox, .dark-background #sidediv, +.dark-background #chatbox, .dark-background #outerdocbody, .dark-background { + --text-color: var(--super-light-color); + --text-soft-color: var(--light-color); + --border-color: var(--super-dark-color); + --bg-soft-color: var(--super-dark-color); + --bg-color: var(--dark-color); +} +.dark-background body, .full-width-editor.dark-editor body:not(.comments-active) { + --scrollbar-bg: var(--dark-color); + --scrollbar-track: var(--super-dark-color); + --scrollbar-thumb: var(--light-color); +} +.dark-background .compact-display-content { + background-color: var(--dark-color); +} +/* Special combinaison with toolbar */ +.dark-background.dark-toolbar .popup-content, .dark-editor.dark-toolbar .popup-content { + box-shadow: 0 0 14px 0px var(--super-dark-color); +} + + + + + +/* ======================== */ +/* == Super Light Editor == */ +/* ======================== */ +.super-light-editor #outerdocbody iframe, .super-light-editor #outerdocbody > #innerdocbody { + --bg-color: var(--super-light-color); +} +.super-light-editor #innerdocbody { + --text-color: var(--super-dark-color); +} +/* ================== */ +/* == Light Editor == */ +/* ================== */ +.light-editor #outerdocbody iframe, .light-editor #outerdocbody > #innerdocbody { + --bg-color: var(--light-color); +} +.light-editor #innerdocbody { + --text-color: var(--super-dark-color); +} +/* ======================= */ +/* == Super Dark Editor == */ +/* ======================= */ +.super-dark-editor #outerdocbody iframe, .super-dark-editor #outerdocbody > #innerdocbody { + --bg-color: var(--super-dark-color); +} +.super-dark-editor #innerdocbody { + --text-color: var(--super-light-color); +} +/* ================= */ +/* == Dark Editor == */ +/* ================= */ +.dark-editor #outerdocbody iframe, .dark-editor #outerdocbody > #innerdocbody { + --bg-color: var(--dark-color); +} +.dark-editor #innerdocbody { + --text-color: var(--super-light-color); +} + + +/* ======================================== */ +/* == Combinaison with background/editor == */ +/* ======================================== */ +.super-light-editor.super-light-background #outerdocbody, +.light-editor.light-background #outerdocbody, +.super-dark-editor.super-dark-background #outerdocbody, +.dark-editor.dark-background #outerdocbody { + padding-top: 0; +} +@media (min-width: 1001px) { + .super-light-editor.super-light-background, + .light-editor.light-background, + .super-dark-editor.super-dark-background, + .dark-editor.dark-background { + --editor-horizontal-padding: 35px; + --editor-vertical-padding: 20px; + } +} + +/* ===================================== */ +/* == Combinaison with toolbar/editor == */ +/* ===================================== */ +.super-light-editor.super-light-toolbar .toolbar, +.light-editor.light-toolbar .toolbar, +.super-dark-editor.super-dark-toolbar .toolbar, +.dark-editor.dark-toolbar .toolbar { + --toolbar-border: 1px solid var(--border-color); +} + + +/* ======================= */ +/* == Full Width Editor == */ +/* ======================= */ +.full-width-editor #outerdocbody iframe, .full-width-editor #outerdocbody > #innerdocbody { + max-width: none !important; + border-radius: 0; +} +.full-width-editor #outerdocbody { + padding: 0; + margin: 0; +} +@media (min-width: 1001px) { + .full-width-editor { + --editor-horizontal-padding: 35px !important; + --editor-vertical-padding: 20px !important; + } +} +.full-width-editor ::-webkit-scrollbar-track, +.full-width-editor ::-webkit-scrollbar-thumb { + border-radius: 0px; +} \ No newline at end of file diff --git a/src/static/skins/colibris/src/plugins/brightcolorpicker.css b/src/static/skins/colibris/src/plugins/brightcolorpicker.css index 32480cc9c5f..8db2880c12c 100644 --- a/src/static/skins/colibris/src/plugins/brightcolorpicker.css +++ b/src/static/skins/colibris/src/plugins/brightcolorpicker.css @@ -1,13 +1,7 @@ -#colorpicker { - left: -200px !important; - top: 0px !important; -} - #colorpicker a.brightColorPicker-cancelButton { background: none; padding: 0; padding-top: 10px; - font-family: Arial, sans-serif; font-weight: bold; border: none; } diff --git a/src/static/skins/colibris/src/plugins/comments.css b/src/static/skins/colibris/src/plugins/comments.css new file mode 100644 index 00000000000..005890ef484 --- /dev/null +++ b/src/static/skins/colibris/src/plugins/comments.css @@ -0,0 +1,112 @@ +.sidebar-comment .btn { + margin-top: 10px; + padding: 3px 8px; + font-size: .9rem; + margin: 10px 0 5px 0; +} +.sidebar-comment .btn.btn-primary:not(#comment-create-btn) { + background-color: #576273; + background-color: var(--text-soft-color); +} +.sidebar-comment .suggestion-create { + margin-top: 10px; +} +.suggestion-display .from-value, .suggestion-display .to-value { + color: #64d29b; + color: var(--primary-color); + font-weight: bold; + opacity: 1; +} +.suggestion-display .from-value { + margin-right: 5px; +} +.comment-actions-wrapper .buttonicon { + opacity: .8; +} +.comment-actions-wrapper .buttonicon:hover { + opacity: 1; +} +.comment-actions-wrapper .comment-edit { + margin-right: 5px; +} +[type="checkbox"] + label.label-suggestion-checkbox { + margin-left: 5px; + padding-left: 2.4rem; +} +.sidebar-comment .full-display-content { + margin-left: -10px; + box-shadow: none; + background-color: #f2f3f4; + background-color: var(--bg-soft-color); + border: 1px solid #ffffff; + border: 1px solid var(--bg-color); +} +.comment-reply { + border-top: 1px solid #ffffff; + border-top: 1px solid var(--bg-color); + background-color: inherit; +} +.comment-reply textarea, .comment-reply input[type="text"] { + background-color: #ffffff; + background-color: var(--bg-color); +} +.btn.revert-suggestion-btn { + padding-left: 0; +} +.comment-edit-form { + margin-top: 15px; +} + +/* MODAL */ +.comment-modal .full-display-content { + box-shadow: none; + margin: 0 !important; + border: none; + background-color: #ffffff; + background-color: var(--bg-color); +} +.comment-modal .comment-modal-comment { + padding: 0; +} +.comment-modal .comment-reply textarea, .comment-modal .comment-reply input[type="text"] { + background-color: #f2f3f4; + background-color: var(--bg-soft-color); +} +.comment-modal .comment-reply { + border-top: 1px solid #f2f3f4; + border-top: 1px solid var(--bg-soft-color); +} +.comment-modal .full-display-content .comment-title-wrapper, +.comment-modal .full-display-content .comment-reply { + padding: 15px; +} + + +/* NEW COMMENT POPUP */ +.new-comment-popup textarea { + background-color: #f2f3f4; + background-color: var(--bg-soft-color); +} +.new-comment-popup .suggestion { + margin-bottom: 10px; +} + + +/* EDITOR COMMENTEED LINE */ +#innerdocbody .ace-line .comment { + background-color: #fffacc; + color: var(--super-dark-color); +} + + +@media (min-width: 1200px) { + #comments { + width: 300px; + } + .sidebar-comment .full-display-content { + margin-left: 10px; + } + .compact-display-content { + padding-left: 20px; + } +} \ No newline at end of file diff --git a/src/static/skins/colibris/src/plugins/comments_page.css b/src/static/skins/colibris/src/plugins/comments_page.css deleted file mode 100644 index f11fa61c8a4..00000000000 --- a/src/static/skins/colibris/src/plugins/comments_page.css +++ /dev/null @@ -1,290 +0,0 @@ -.comment.selected { - color: #a28239; -} - -#newComment { - box-shadow: 0 0 0 1px rgba(99, 114, 130, 0.16), 0 8px 16px rgba(27, 39, 51, 0.08); - border: none; - padding: 15px; -} - -p[data-l10n-id="ep_comments_page.comment"] { - font-weight: 900; - font-size: 16px; - text-transform: uppercase; - margin-bottom: 10px; -} - -#newComment.sidebar-comment textarea:not(.comment-suggest-from) { - border: 1px solid #d2d2d2; - border-radius: 3px; - padding: 8px 10px; - height: 80px; - padding: 8px; - font-size: 14px; - width: calc(100% - 15px); -} - -#newComment.sidebar-comment .comment-suggest-from { - height: auto !important; - font-size: 14px; - padding: 8px; - width: calc(100% - 15px) !important; - background-color: #f9f9f9; - margin-top: 8px; - border: 1px solid #f3eeee; - border-left: 4px solid #a7a7a7; - border-radius: 3px; -} - -.comment-suggest { - margin-bottom: 8px; -} - -.reply-comment-suggest input, -.comment-suggest input { - vertical-align: -2px; - margin-right: 5px; -} - -.reply-comment-suggest label, -.comment-suggest label { - font-style: italic; - font-weight: normal; -} - -.sidebar-comment input, -.comment-buttons input { - border-radius: 4px; - text-transform: uppercase; - font-weight: 900; - font-size: 13px; - line-height: 1.5; - width: auto; - border: none; -} - -#newComment.sidebar-comment input[type=submit] { - color: white; - margin-right: 10px; - padding: 0 10px; - border: none; -} - -#newComment.sidebar-comment input[type=reset] { - background-color: white; - border: none; -} - -.comment-content:focus { - border: 2px solid rgba(33, 150, 243, 0.51); -} - -.comment-changeTo-approve input[type=submit] { width: 100%; font-size: 12px;} - -.reply-comment-suggest-from-p, -.comment-changeFrom-value, -.comment-changeTo-value, -.reply-suggestion .reply-comment-suggest-from, -.suggestion .comment-suggest-from { - border: none; - font-weight: normal; - font-style: italic; - padding-left: 0; - width: 100% !important; - padding: 0; - padding-top: 8px; - /* width: inherit !important; */ - /*color: rgba(41, 125, 191, 0.85);*/ -} - -textarea.comment-suggest-to { - margin-bottom: 8px; -} - -.suggestion { - font-weight: bold; - font-size: 11px; - text-transform: uppercase; -} - -#comments { - top: 82px; -} - -#comments .sidebar-comment { - background-color: transparent; - font-size: 13px; - border: none; - box-shadow: none; -} - -@media (min-width: 1200px) { - #comments .sidebar-comment:hover, - #comments .sidebar-comment.mouseover, - .comment-modal { - margin-right: -30px; - } -} - -#comments .sidebar-comment:hover, -#comments .sidebar-comment.mouseover, -.comment-modal { - background-color: #fff; - padding: 0; - padding-top: 10px; - margin-top: -8px; - width: 250px; - box-shadow: 0 0 0 1px rgba(99, 114, 130, 0.16), 0 8px 16px rgba(27, 39, 51, 0.08); -} - -#comments .sidebar-comment:hover time, -#comments .sidebar-comment.mouseover time, -.comment-modal-comment>time { - display: block !important; -} - -#comments .sidebar-comment:hover>section, -#comments .sidebar-comment.mouseover>section, -.comment-modal-comment>section { - padding: 0 15px; - padding-bottom: 10px; - margin-top: 5px; - display: block; - line-height: 20px; - margin-top: 8px; -} - -.comment-delete-container { - float: right; - margin: 0; - height: 15px; - font-size: 15px; - background-color: transparent; - padding: 6px 15px 4px 8px; - color: #7b7777; -} - -.comment-reply { - border-top: 1px solid #d2d2d2; - background-color: #f9f9f9; - margin: 0; - padding: 10px 15px 3px; -} - -.comment-reply-input-label span { - font-weight: bold; -} - -.comment-reply-input { - border: 1px solid #d2d2d2 !important; - width: calc(100% - 20px) !important; - padding: 8px 10px; - text-transform: none !important; - margin-top: 5px; - margin-bottom: 10px; - font-weight: normal; -} - -.reply-suggestion p:not(.reply-comment-suggest-from-p) { - text-transform: uppercase; - font-size: 11px; - font-weight: 400; - text-transform: uppercase; -} - -.comment-changeTo-approve input { - height: 25px; - margin: 0; - margin-top: 5px; -} - -.reply-suggestion { - margin-top: 8px; -} - -.reply-comment-suggest-from-p { - padding: 0 -} - -.comment-text { - font-weight: normal; - line-height: 20px; -} - -.sidebar-comment-reply:nth-child(even) { - background-color: transparent; -} - -.sidebar-comment-reply { - padding: 0; - margin-bottom: 10px; -} - -.comment-author-name { - font-style: normal; -} - -.comment-changeFrom-label, -.comment-changeTo-label { - text-transform: uppercase; - font-size: 11px; -} - -.comment-reply note { - line-height: 16px; -} - -.reply-comment-suggest { - display: none !important -} - -.comment-changeTo-form { - margin-bottom: 5px; - padding: 0 15px; -} - -.sidebar-comment>.comment-author-name, -.comment-modal-comment>.comment-author-name { - padding-left: 0px; -} - -#comments .sidebar-comment:hover >.comment-author-name, -#comments .sidebar-comment.mouseover >.comment-author-name { - margin-top: 2px; - display: inline-block; - padding-left: 15px; -} - -.sidebar-comment>time, -.comment-modal-comment>time { - position: absolute; - top: 11px; - font-size: 11px; - right: 36px; - color: #555555; - font-style: italic; -} - -.comment-changeTo-approve { - margin-bottom: 14px; - margin-top: 5px; -} - -.comment-reply note:first-child { - margin-top: 8px; -} - -.comment-modal { - padding: 0; - border: none; - width: 350px !important; - margin-top: 0; - padding-top: 10px; -} - -.comment-modal-comment>.comment-author-name { - padding-left: 14px; -} - - diff --git a/src/static/skins/colibris/src/plugins/cursortrace.css b/src/static/skins/colibris/src/plugins/cursortrace.css deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/src/static/skins/colibris/src/plugins/embedded_hyperlinks.css b/src/static/skins/colibris/src/plugins/embedded_hyperlinks.css deleted file mode 100644 index b5ec7e61cb8..00000000000 --- a/src/static/skins/colibris/src/plugins/embedded_hyperlinks.css +++ /dev/null @@ -1,6 +0,0 @@ -.hyperlink-dialog>.hyperlink-save{ - height: 34px; - margin-top: 1px; - margin-right: 0; - margin-left: 2px; -} \ No newline at end of file diff --git a/src/static/skins/colibris/src/plugins/font_color.css b/src/static/skins/colibris/src/plugins/font_color.css index 4ecd5c1cd01..95f81cf31a2 100644 --- a/src/static/skins/colibris/src/plugins/font_color.css +++ b/src/static/skins/colibris/src/plugins/font_color.css @@ -1,32 +1,38 @@ -li.acl-write.font-color-icon.plugin-ep_font_color { - display: none; +.font-color-icon { + display: none !important; } #font-color { display: list-item !important; } +.color\:black, +[data-color=black] { + color: #485365; + color: var(--text-color); +} + .color\:red, [data-color=red] { - color: #F44336; + color: #F44336; } .color\:green, [data-color=green] { - color: #66d29c; + color: #66d29c; } .color\:blue, [data-color=blue] { - color: #2196f3; + color: #2196f3; } .color\:yellow, [data-color=yellow] { - color: #e0d776; + color: #ffeb3b; } .color\:orange, [data-color=orange] { - color: #d2a564; + color: #FF9800; } \ No newline at end of file diff --git a/src/static/skins/colibris/src/plugins/set_title_on_pad.css b/src/static/skins/colibris/src/plugins/set_title_on_pad.css deleted file mode 100644 index 94b19520318..00000000000 --- a/src/static/skins/colibris/src/plugins/set_title_on_pad.css +++ /dev/null @@ -1,34 +0,0 @@ -#pad_title { - margin-bottom: 15px !important; - margin-top: 5px !important; - display: none; /* display only when page is loaded via javascript */ -} - -@media (max-width:720px) { - #pad_title { display: none !important; } -} - -#edit_title { - color: white; -} -#edit_title:before { - font-family: fontawesome-etherpad; - position: absolute; - top: 20px; - font-size: 14px; - content: "\E839"; - margin-left: 10px; -} - -#input_title { - background-color: #f9f9f9 !important; - height: auto !important; - margin-top: 3px; - width: calc(100% - 110px) !important; - padding: 8px 10px !important; -} - -#save_title button { - height: 30px !important; - padding: 5px 20px !important; -} \ No newline at end of file diff --git a/src/static/skins/colibris/timeslider.css b/src/static/skins/colibris/timeslider.css index ba5199baa97..b7b9f3e1045 100644 --- a/src/static/skins/colibris/timeslider.css +++ b/src/static/skins/colibris/timeslider.css @@ -1,142 +1,98 @@ -@media (max-width: 600px) { html { overflow: hidden } } - -@media (max-width: 1100px) { - .timeslider #padeditor { - padding: 0 !important; - } -} - -.timeslider #import_export, .timeslider #settings{ - top: 108px !important; - right: 55px; -} - -.timeslider #export > p { - font-size: 15px; - margin-top: 0; - margin-bottom: 20px; +#timeslider-slider #ui-slider-handle { + border-radius: 3px; + width: 12px; + height: 28px; + background-color: #64d29b; + background-color: var(--primary-color); } -.timeslider #padpage { - display: flex; - flex-direction: column; +#timeslider-slider #ui-slider-bar { + border-radius: 3px; + background-color: #d2d2d2; + background-color: var(--border-color); } - -.timeslider #timeslider-top { - position: relative; - border-bottom: 1px solid #e4e4e4; +#slider-btn-container { + margin: -18px 15px 0 20px; } - -.timeslider-bar { background: none; } -.timeslider-bar p { margin: 8px; font-size: 12px;} - -.timeslider-bar #editbar { +#slider-btn-container #playpause_button_icon { + color: #ffffff; + color: var(--bg-color); + background-color: #64d29b; + background-color: var(--primary-color); border: none; - background: none !important; - margin-right: 10px; -} - -.timeslider #padmain { - position: relative; - top: 0 !important; - flex: 1 auto; - overflow: auto; -} - -.timeslider #padeditor { - height: 100%; - padding-top: 30px; -} - -.timeslider #editorcontainerbox { - height: 100%; - overflow: visible; - margin-top: 0 !important; + margin-right: 5px; + padding-top: 3px; + width: 45px; + height: 45px; +} +#slider-btn-container #playpause_button_icon:not(.pause) { + padding-left: 4px; +} +#slider-btn-container .stepper { + border: 2px solid !important; + height: 30px; + width: 30px; + line-height: 28px; + margin-left: 5px; + font-size: 13px; + color: #64d29b; + color: var(--primary-color); + border-color: #64d29b; + border-color: var(--primary-color); } - -#timeslider { - margin-top: -20px; - margin-left: 0; - background-color: transparent; +#slider-btn-container .stepper.disabled { + opacity: .5; } -#timeslider, #timeslider-left, #timeslider-right { - height: 57px; - background-color: transparent; -} - -#timeslider #timer { - opacity: 0.8; - font-style: italic; - right: 158px; - top: -3px; - left: initial; - background: none; +.timeslider #editbar .buttontext { + background-color: #576273; + background-color: var(--text-soft-color); + color: #ffffff; + color: var(--bg-color); + margin: 0; } -#timeslider #timeslider-slider { margin-left: 4px; } - -#ui-slider-handle { - z-index: 5; - border-radius: 3px; - height: 28px; - top: 19px; +#editbar { + display: block; + padding-bottom: 5px; } -#ui-slider-bar { - height: 10px; - margin-top: 28px; - margin-right: 180px; +#editbar li > a { border-radius: 3px; - background-color: #e4e4e4; -} - -#timeslider .star { - top: 25px; -} -#timeslider .star:before { - color: #da9700; - content: "\e836"; } -.timeslider #editbar .buttontext { - color: white; - margin: 0; -} -.timeslider #editbar .grouped-right { - margin: 0; padding: 0; - margin-top: 5px; - margin-left: 5px; +#timeslider-slider #timer { + opacity: .7; + top: -12px; + font-size: .8em; } -.timeslider #playpause_button { - right: 95px; - top: 1px; -} -#playpause_button_icon { - border:none; +.timeslider #authorsList .author { + padding: 2px 5px; + border-radius: 3px; + margin-right: 4px; + margin-bottom: 4px; } -#playpause_button_icon:before { color: white; } -.timeslider #leftstep { - right: 60px; - top: 12px; +.timeslider-title { + font-size: 1.8rem !important; } - -.timeslider #rightstep { - top: 12px; - right: 30px; +.timeslider-subtitle { + margin-top: 6px; + font-size: .9em; } -.stepper { - border: 2px solid; - text-align: center; - border-radius: 50%; - height: 25px; - padding-top: 2px; -} +@media (max-width: 720px) { -.timeslider #authorsList .author { - padding: 2px 5px; - border-radius: 3px; + #slider-btn-container { + margin-top: 0; + margin-right: 5px; + } + #slider-btn-container #playpause_button_icon { + width: 30px; + height: 30px; + } + #slider-btn-container #playpause_button_icon:before { + font-size: 18px; + } } \ No newline at end of file diff --git a/src/static/skins/colibris/timeslider.js b/src/static/skins/colibris/timeslider.js index c94a55778df..1322ec4c8ef 100644 --- a/src/static/skins/colibris/timeslider.js +++ b/src/static/skins/colibris/timeslider.js @@ -1,6 +1,3 @@ function customStart() { - console.log("custom start", $('#timeslider-wrapper').length); - // inverse display order betwwen slidebar and titles - $('#timeslider-wrapper').appendTo('#timeslider-top'); } diff --git a/src/static/skins/no-skin/pad.css b/src/static/skins/no-skin/pad.css index b8cdb4642b6..e69de29bb2d 100644 --- a/src/static/skins/no-skin/pad.css +++ b/src/static/skins/no-skin/pad.css @@ -1,5 +0,0 @@ -@media (max-width:600px) { - #sidediv { - display: none !important; - } -} \ No newline at end of file diff --git a/src/templates/pad.html b/src/templates/pad.html index 34bcf05997d..45f9a7d3dab 100644 --- a/src/templates/pad.html +++ b/src/templates/pad.html @@ -5,346 +5,377 @@ ; %> + <% e.begin_block("htmlHead"); %> - + <% e.end_block(); %> - <%=settings.title%> - + |@licend The above is the entire license notice + for the JavaScript code in this page.| + */ + - - - - - + + + + + - <% e.begin_block("styles"); %> - + <% e.begin_block("styles"); %> + - <% e.begin_block("customStyles"); %> - - <% e.end_block(); %> + <% e.begin_block("customStyles"); %> + + <% e.end_block(); %> - - <% e.end_block(); %> + + <% e.end_block(); %> - - - + + + - + - <% e.begin_block("body"); %> -
      -
      -
      -
      + <% e.begin_block("body"); %> - - -
      - <% e.begin_block("afterEditbar"); %><% e.end_block(); %> + + + +
      +
      + + + + +
      + + <% e.begin_block("afterEditbar"); %><% e.end_block(); %> + +
      + + <% e.begin_block("editorContainerBox"); %> -
      + + + + +
      + +
      +
      +

      You need a password to access this pad

      +
      + +
      +
      +
      +

      You do not have permission to access this pad

      +
      +
      +

      Your password was wrong

      +
      +
      +

      Cookie could not be found. Please allow cookies in your browser!

      +
      + <% e.begin_block("loading"); %> +

      Loading...

      + <% e.end_block(); %> + +
      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
      + + + + + +
      - - - - + + + -
      +
      0
      -
      - - █   +
      +
      +

      + + █  
      -
      +
      @@ -353,89 +384,134 @@

      +
      +
      +
      + + + + + <% if (settings.skinName == 'colibris') { %> + + <% } %> + + <% e.end_block(); %> + +
      + + <% e.end_block(); %> + + + + + + + <% e.begin_block("scripts"); %> + + + + + + + + + + + + + + + <% e.begin_block("customScripts"); %> + + <% e.end_block(); %> + + + + + <% e.end_block(); %> diff --git a/src/templates/timeslider.html b/src/templates/timeslider.html index 60194af12da..2368f0ea1fd 100644 --- a/src/templates/timeslider.html +++ b/src/templates/timeslider.html @@ -3,7 +3,7 @@ , langs = require("ep_etherpad-lite/node/hooks/i18n").availableLangs %> - + <%=settings.title%> Timeslider @@ -273,5 +297,4 @@

      <% e.end_block(); %> - diff --git a/tests/backend/loadSettings.js b/tests/backend/loadSettings.js deleted file mode 100644 index f208fe3d04e..00000000000 --- a/tests/backend/loadSettings.js +++ /dev/null @@ -1,17 +0,0 @@ -var jsonminify = require(__dirname+"/../../src/node_modules/jsonminify"); - -function loadSettings(){ - var settingsStr = fs.readFileSync(__dirname+"/../../settings.json").toString(); - // try to parse the settings - var settings; - try { - if(settingsStr) { - settingsStr = jsonminify(settingsStr).replace(",]","]").replace(",}","}"); - return JSON.parse(settingsStr); - } - }catch(e){ - console.error("whoops something is bad with settings"); - } -} - -exports.loadSettings = loadSettings; diff --git a/tests/backend/specs/api/api.js b/tests/backend/specs/api/api.js new file mode 100644 index 00000000000..0b372de852b --- /dev/null +++ b/tests/backend/specs/api/api.js @@ -0,0 +1,79 @@ +/** + * API specs + * + * Tests for generic overarching HTTP API related features not related to any + * specific part of the data model or domain. For example: tests for versioning + * and openapi definitions. + */ + +const assert = require('assert'); +const supertest = require(__dirname + '/../../../../src/node_modules/supertest'); +const fs = require('fs'); +const settings = require(__dirname + '/../../../../src/node/utils/Settings'); +const api = supertest('http://' + settings.ip + ':' + settings.port); +const path = require('path'); + +var validateOpenAPI = require(__dirname + '/../../../../src/node_modules/openapi-schema-validation').validate; + +var filePath = path.join(__dirname, '../../../../APIKEY.txt'); + +var apiKey = fs.readFileSync(filePath, { encoding: 'utf-8' }); +apiKey = apiKey.replace(/\n$/, ''); +var apiVersion = 1; + +var testPadId = makeid(); + +describe('API Versioning', function() { + it('errors if can not connect', function(done) { + api + .get('/api/') + .expect(function(res) { + apiVersion = res.body.currentVersion; + if (!res.body.currentVersion) throw new Error('No version set in API'); + return; + }) + .expect(200, done); + }); +}); + +describe('OpenAPI definition', function() { + it('generates valid openapi definition document', function(done) { + api + .get('/api/openapi.json') + .expect(function(res) { + const { valid, errors } = validateOpenAPI(res.body, 3); + if (!valid) { + const prettyErrors = JSON.stringify(errors, null, 2); + throw new Error(`Document is not valid OpenAPI. ${errors.length} validation errors:\n${prettyErrors}`); + } + return; + }) + .expect(200, done); + }); +}); + +describe('jsonp support', function() { + it('supports jsonp calls', function(done) { + api + .get(endPoint('createPad') + '&jsonp=jsonp_1&padID=' + testPadId) + .expect(function(res) { + if (!res.text.match('jsonp_1')) throw new Error('no jsonp call seen'); + }) + .expect('Content-Type', /javascript/) + .expect(200, done); + }); +}); + +var endPoint = function(point) { + return '/api/' + apiVersion + '/' + point + '?apikey=' + apiKey; +}; + +function makeid() { + var text = ''; + var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + + for (var i = 0; i < 5; i++) { + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return text; +} diff --git a/tests/backend/specs/api/characterEncoding.js b/tests/backend/specs/api/characterEncoding.js new file mode 100644 index 00000000000..83145089f49 --- /dev/null +++ b/tests/backend/specs/api/characterEncoding.js @@ -0,0 +1,113 @@ +/* + * This file is copied & modified from /tests/backend/specs/api/pad.js + * + * TODO: maybe unify those two files and merge in a single one. + */ + +const assert = require('assert'); +const supertest = require(__dirname+'/../../../../src/node_modules/supertest'); +const fs = require('fs'); +const settings = require(__dirname + '/../../../../src/node/utils/Settings'); +const api = supertest('http://'+settings.ip+":"+settings.port); +const path = require('path'); +const async = require(__dirname+'/../../../../src/node_modules/async'); + +var filePath = path.join(__dirname, '../../../../APIKEY.txt'); + +var apiKey = fs.readFileSync(filePath, {encoding: 'utf-8'}); +apiKey = apiKey.replace(/\n$/, ""); +var apiVersion = 1; +var testPadId = makeid(); + +describe('Connectivity For Character Encoding', function(){ + it('can connect', function(done) { + api.get('/api/') + .expect('Content-Type', /json/) + .expect(200, done) + }); +}) + +describe('API Versioning', function(){ + it('finds the version tag', function(done) { + api.get('/api/') + .expect(function(res){ + apiVersion = res.body.currentVersion; + if (!res.body.currentVersion) throw new Error("No version set in API"); + return; + }) + .expect(200, done) + }); +}) + +describe('Permission', function(){ + it('errors with invalid APIKey', function(done) { + // This is broken because Etherpad doesn't handle HTTP codes properly see #2343 + // If your APIKey is password you deserve to fail all tests anyway + var permErrorURL = '/api/'+apiVersion+'/createPad?apikey=password&padID=test'; + api.get(permErrorURL) + .expect(401, done) + }); +}) + +describe('createPad', function(){ + it('creates a new Pad', function(done) { + api.get(endPoint('createPad')+"&padID="+testPadId) + .expect(function(res){ + if(res.body.code !== 0) throw new Error("Unable to create new Pad"); + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); +}) + +describe('setHTML', function(){ + it('Sets the HTML of a Pad attempting to weird utf8 encoded content', function(done) { + fs.readFile('../tests/backend/specs/api/emojis.html', 'utf8', function(err, html) { + api.post(endPoint('setHTML')) + .send({ + "padID": testPadId, + "html": html, + }) + .expect(function(res){ + if(res.body.code !== 0) throw new Error("Can't set HTML properly"); + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); + }); +}) + +describe('getHTML', function(){ + it('get the HTML of Pad with emojis', function(done) { + api.get(endPoint('getHTML')+"&padID="+testPadId) + .expect(function(res){ + if (res.body.data.html.indexOf("🇼") === -1) { + throw new Error("Unable to get the HTML"); + } + }) + .expect('Content-Type', /json/) + .expect(200, done) + }); +}) + +/* + + End of test + +*/ + +var endPoint = function(point, version){ + version = version || apiVersion; + return '/api/'+version+'/'+point+'?apikey='+apiKey; +} + +function makeid() +{ + var text = ""; + var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + for( var i=0; i < 10; i++ ){ + text += possible.charAt(Math.floor(Math.random() * possible.length)); + } + return text; +} diff --git a/tests/backend/specs/api/chat.js b/tests/backend/specs/api/chat.js index 2bcd9783add..e2ce59b1c3b 100644 --- a/tests/backend/specs/api/chat.js +++ b/tests/backend/specs/api/chat.js @@ -1,7 +1,7 @@ var assert = require('assert') supertest = require(__dirname+'/../../../../src/node_modules/supertest'), fs = require('fs'), - settings = require(__dirname+'/../../loadSettings').loadSettings(), + settings = require(__dirname + '/../../../../src/node/utils/Settings'), api = supertest('http://'+settings.ip+":"+settings.port), path = require('path'); diff --git a/tests/backend/specs/api/emojis.html b/tests/backend/specs/api/emojis.html new file mode 100644 index 00000000000..a0e3d2752f6 --- /dev/null +++ b/tests/backend/specs/api/emojis.html @@ -0,0 +1,10 @@ + + + + foo + + + +😀 😁 😂 🤣 😃 😄 😅 😆 😉 😊 😋 😎 😍 😘 🥰 😗 😙 😚 ☺️ 🙂 🤗 🤩 🤔 🤨 😐 😑 😶 🙄 😏 😣 😥 😮 🤐 😯 😪 😫 😴 😌 😛 😜 😝 🤤 😒 😓 😔 😕 🙃 🤑 😲 ☹️ 🙁 😖 😞 😟 😤 😢 😭 😦 😧 😨 😩 🤯 😬 😰 😱 🥵 🥶 😳 🤪 😵 😡 😠 🤬 😷 🤒 🤕 🤢 🤮 🤧 😇 🤠 🤡 🥳 🥴 🥺 🤥 🤫 🤭 🧐 🤓 😈 👿 👹 👺 💀 👻 👽 🤖 💩 😺 😸 😹 😻 😼 😽 🙀 😿 😾 👶 👧 🧒 👦 👩 🧑 👨 👵 🧓 👴 👲 👳‍♀️ 👳‍♂️ 🧕 🧔 👱‍♂️ 👱‍♀️ 👨‍🦰 👩‍🦰 👨‍🦱 👩‍🦱 👨‍🦲 👩‍🦲 👨‍🦳 👩‍🦳 🦸‍♀️ 🦸‍♂️ 🦹‍♀️ 🦹‍♂️ 👮‍♀️ 👮‍♂️ 👷‍♀️ 👷‍♂️ 💂‍♀️ 💂‍♂️ 🕵️‍♀️ 🕵️‍♂️ 👩‍⚕️ 👨‍⚕️ 👩‍🌾 👨‍🌾 👩‍🍳 👨‍🍳 👩‍🎓 👨‍🎓 👩‍🎤 👨‍🎤 👩‍🏫 👨‍🏫 👩‍🏭 👨‍🏭 👩‍💻 👨‍💻 👩‍💼 👨‍💼 👩‍🔧 👨‍🔧 👩‍🔬 👨‍🔬 👩‍🎨 👨‍🎨 👩‍🚒 👨‍🚒 👩‍✈️ 👨‍✈️ 👩‍🚀 👨‍🚀 👩‍⚖️ 👨‍⚖️ 👰 🤵 👸 🤴 🤶 🎅 🧙‍♀️ 🧙‍♂️ 🧝‍♀️ 🧝‍♂️ 🧛‍♀️ 🧛‍♂️ 🧟‍♀️ 🧟‍♂️ 🧞‍♀️ 🧞‍♂️ 🧜‍♀️ 🧜‍♂️ 🧚‍♀️ 🧚‍♂️ 👼 🤰 🤱 🙇‍♀️ 🙇‍♂️ 💁‍♀️ 💁‍♂️ 🙅‍♀️ 🙅‍♂️ 🙆‍♀️ 🙆‍♂️ 🙋‍♀️ 🙋‍♂️ 🤦‍♀️ 🤦‍♂️ 🤷‍♀️ 🤷‍♂️ 🙎‍♀️ 🙎‍♂️ 🙍‍♀️ 🙍‍♂️ 💇‍♀️ 💇‍♂️ 💆‍♀️ 💆‍♂️ 🧖‍♀️ 🧖‍♂️ 💅 🤳 💃 🕺 👯‍♀️ 👯‍♂️ 🕴 🚶‍♀️ 🚶‍♂️ 🏃‍♀️ 🏃‍♂️ 👫 👭 👬 💑 👩‍❤️‍👩 👨‍❤️‍👨 💏 👩‍❤️‍💋‍👩 👨‍❤️‍💋‍👨 👪 👨‍👩‍👧 👨‍👩‍👧‍👦 👨‍👩‍👦‍👦 👨‍👩‍👧‍👧 👩‍👩‍👦 👩‍👩‍👧 👩‍👩‍👧‍👦 👩‍👩‍👦‍👦 👩‍👩‍👧‍👧 👨‍👨‍👦 👨‍👨‍👧 👨‍👨‍👧‍👦 👨‍👨‍👦‍👦 👨‍👨‍👧‍👧 👩‍👦 👩‍👧 👩‍👧‍👦 👩‍👦‍👦 👩‍👧‍👧 👨‍👦 👨‍👧 👨‍👧‍👦 👨‍👦‍👦 👨‍👧‍👧 🤲 👐 🙌 👏 🤝 👍 👎 👊 ✊ 🤛 🤜 🤞 ✌️ 🤟 🤘 👌 👈 👉 👆 👇 ☝️ ✋ 🤚 🖐 🖖 👋 🤙 💪 🦵 🦶 🖕 ✍️ 🙏 💍 💄 💋 👄 👅 👂 👃 👣 👁 👀 🧠 🦴 🦷 🗣 👤 👥🧥 👚 👕 👖 👔 👗 👙 👘 👠 👡 👢 👞 👟 🥾 🥿 🧦 🧤 🧣 🎩 🧢 👒 🎓 ⛑ 👑 👝 👛 👜 💼 🎒 👓 🕶 🥽 🥼 🌂 🧵 🧶👶🏻 👦🏻 👧🏻 👨🏻 👩🏻 👱🏻‍♀️ 👱🏻 👴🏻 👵🏻 👲🏻 👳🏻‍♀️ 👳🏻 👮🏻‍♀️ 👮🏻 👷🏻‍♀️ 👷🏻 💂🏻‍♀️ 💂🏻 🕵🏻‍♀️ 🕵🏻 👩🏻‍⚕️ 👨🏻‍⚕️ 👩🏻‍🌾 👨🏻‍🌾 👩🏻‍🍳 👨🏻‍🍳 👩🏻‍🎓 👨🏻‍🎓 👩🏻‍🎤 👨🏻‍🎤 👩🏻‍🏫 👨🏻‍🏫 👩🏻‍🏭 👨🏻‍🏭 👩🏻‍💻 👨🏻‍💻 👩🏻‍💼 👨🏻‍💼 👩🏻‍🔧 👨🏻‍🔧 👩🏻‍🔬 👨🏻‍🔬 👩🏻‍🎨 👨🏻‍🎨 👩🏻‍🚒 👨🏻‍🚒 👩🏻‍✈️ 👨🏻‍✈️ 👩🏻‍🚀 👨🏻‍🚀 👩🏻‍⚖️ 👨🏻‍⚖️ 🤶🏻 🎅🏻 👸🏻 🤴🏻 👰🏻 🤵🏻 👼🏻 🤰🏻 🙇🏻‍♀️ 🙇🏻 💁🏻 💁🏻‍♂️ 🙅🏻 🙅🏻‍♂️ 🙆🏻 🙆🏻‍♂️ 🙋🏻 🙋🏻‍♂️ 🤦🏻‍♀️ 🤦🏻‍♂️ 🤷🏻‍♀️ 🤷🏻‍♂️ 🙎🏻 🙎🏻‍♂️ 🙍🏻 🙍🏻‍♂️ 💇🏻 💇🏻‍♂️ 💆🏻 💆🏻‍♂️ 🕴🏻 💃🏻 🕺🏻 🚶🏻‍♀️ 🚶🏻 🏃🏻‍♀️ 🏃🏻 🤲🏻 👐🏻 🙌🏻 👏🏻 🙏🏻 👍🏻 👎🏻 👊🏻 ✊🏻 🤛🏻 🤜🏻 🤞🏻 ✌🏻 🤟🏻 🤘🏻 👌🏻 👈🏻 👉🏻 👆🏻 👇🏻 ☝🏻 ✋🏻 🤚🏻 🖐🏻 🖖🏻 👋🏻 🤙🏻 💪🏻 🖕🏻 ✍🏻 🤳🏻 💅🏻 👂🏻 👃🏻👶🏼 👦🏼 👧🏼 👨🏼 👩🏼 👱🏼‍♀️ 👱🏼 👴🏼 👵🏼 👲🏼 👳🏼‍♀️ 👳🏼 👮🏼‍♀️ 👮🏼 👷🏼‍♀️ 👷🏼 💂🏼‍♀️ 💂🏼 🕵🏼‍♀️ 🕵🏼 👩🏼‍⚕️ 👨🏼‍⚕️ 👩🏼‍🌾 👨🏼‍🌾 👩🏼‍🍳 👨🏼‍🍳 👩🏼‍🎓 👨🏼‍🎓 👩🏼‍🎤 👨🏼‍🎤 👩🏼‍🏫 👨🏼‍🏫 👩🏼‍🏭 👨🏼‍🏭 👩🏼‍💻 👨🏼‍💻 👩🏼‍💼 👨🏼‍💼 👩🏼‍🔧 👨🏼‍🔧 👩🏼‍🔬 👨🏼‍🔬 👩🏼‍🎨 👨🏼‍🎨 👩🏼‍🚒 👨🏼‍🚒 👩🏼‍✈️ 👨🏼‍✈️ 👩🏼‍🚀 👨🏼‍🚀 👩🏼‍⚖️ 👨🏼‍⚖️ 🤶🏼 🎅🏼 👸🏼 🤴🏼 👰🏼 🤵🏼 👼🏼 🤰🏼 🙇🏼‍♀️ 🙇🏼 💁🏼 💁🏼‍♂️ 🙅🏼 🙅🏼‍♂️ 🙆🏼 🙆🏼‍♂️ 🙋🏼 🙋🏼‍♂️ 🤦🏼‍♀️ 🤦🏼‍♂️ 🤷🏼‍♀️ 🤷🏼‍♂️ 🙎🏼 🙎🏼‍♂️ 🙍🏼 🙍🏼‍♂️ 💇🏼 💇🏼‍♂️ 💆🏼 💆🏼‍♂️ 🕴🏼 💃🏼 🕺🏼 🚶🏼‍♀️ 🚶🏼 🏃🏼‍♀️ 🏃🏼 🤲🏼 👐🏼 🙌🏼 👏🏼 🙏🏼 👍🏼 👎🏼 👊🏼 ✊🏼 🤛🏼 🤜🏼 🤞🏼 ✌🏼 🤟🏼 🤘🏼 👌🏼 👈🏼 👉🏼 👆🏼 👇🏼 ☝🏼 ✋🏼 🤚🏼 🖐🏼 🖖🏼 👋🏼 🤙🏼 💪🏼 🖕🏼 ✍🏼 🤳🏼 💅🏼 👂🏼 👃🏼👶🏽 👦🏽 👧🏽 👨🏽 👩🏽 👱🏽‍♀️ 👱🏽 👴🏽 👵🏽 👲🏽 👳🏽‍♀️ 👳🏽 👮🏽‍♀️ 👮🏽 👷🏽‍♀️ 👷🏽 💂🏽‍♀️ 💂🏽 🕵🏽‍♀️ 🕵🏽 👩🏽‍⚕️ 👨🏽‍⚕️ 👩🏽‍🌾 👨🏽‍🌾 👩🏽‍🍳 👨🏽‍🍳 👩🏽‍🎓 👨🏽‍🎓 👩🏽‍🎤 👨🏽‍🎤 👩🏽‍🏫 👨🏽‍🏫 👩🏽‍🏭 👨🏽‍🏭 👩🏽‍💻 👨🏽‍💻 👩🏽‍💼 👨🏽‍💼 👩🏽‍🔧 👨🏽‍🔧 👩🏽‍🔬 👨🏽‍🔬 👩🏽‍🎨 👨🏽‍🎨 👩🏽‍🚒 👨🏽‍🚒 👩🏽‍✈️ 👨🏽‍✈️ 👩🏽‍🚀 👨🏽‍🚀 👩🏽‍⚖️ 👨🏽‍⚖️ 🤶🏽 🎅🏽 👸🏽 🤴🏽 👰🏽 🤵🏽 👼🏽 🤰🏽 🙇🏽‍♀️ 🙇🏽 💁🏽 💁🏽‍♂️ 🙅🏽 🙅🏽‍♂️ 🙆🏽 🙆🏽‍♂️ 🙋🏽 🙋🏽‍♂️ 🤦🏽‍♀️ 🤦🏽‍♂️ 🤷🏽‍♀️ 🤷🏽‍♂️ 🙎🏽 🙎🏽‍♂️ 🙍🏽 🙍🏽‍♂️ 💇🏽 💇🏽‍♂️ 💆🏽 💆🏽‍♂️ 🕴🏼 💃🏽 🕺🏽 🚶🏽‍♀️ 🚶🏽 🏃🏽‍♀️ 🏃🏽 🤲🏽 👐🏽 🙌🏽 👏🏽 🙏🏽 👍🏽 👎🏽 👊🏽 ✊🏽 🤛🏽 🤜🏽 🤞🏽 ✌🏽 🤟🏽 🤘🏽 👌🏽 👈🏽 👉🏽 👆🏽 👇🏽 ☝🏽 ✋🏽 🤚🏽 🖐🏽 🖖🏽 👋🏽 🤙🏽 💪🏽 🖕🏽 ✍🏽 🤳🏽 💅🏽 👂🏽 👃🏽👶🏾 👦🏾 👧🏾 👨🏾 👩🏾 👱🏾‍♀️ 👱🏾 👴🏾 👵🏾 👲🏾 👳🏾‍♀️ 👳🏾 👮🏾‍♀️ 👮🏾 👷🏾‍♀️ 👷🏾 💂🏾‍♀️ 💂🏾 🕵🏾‍♀️ 🕵🏾 👩🏾‍⚕️ 👨🏾‍⚕️ 👩🏾‍🌾 👨🏾‍🌾 👩🏾‍🍳 👨🏾‍🍳 👩🏾‍🎓 👨🏾‍🎓 👩🏾‍🎤 👨🏾‍🎤 👩🏾‍🏫 👨🏾‍🏫 👩🏾‍🏭 👨🏾‍🏭 👩🏾‍💻 👨🏾‍💻 👩🏾‍💼 👨🏾‍💼 👩🏾‍🔧 👨🏾‍🔧 👩🏾‍🔬 👨🏾‍🔬 👩🏾‍🎨 👨🏾‍🎨 👩🏾‍🚒 👨🏾‍🚒 👩🏾‍✈️ 👨🏾‍✈️ 👩🏾‍🚀 👨🏾‍🚀 👩🏾‍⚖️ 👨🏾‍⚖️ 🤶🏾 🎅🏾 👸🏾 🤴🏾 👰🏾 🤵🏾 👼🏾 🤰🏾 🙇🏾‍♀️ 🙇🏾 💁🏾 💁🏾‍♂️ 🙅🏾 🙅🏾‍♂️ 🙆🏾 🙆🏾‍♂️ 🙋🏾 🙋🏾‍♂️ 🤦🏾‍♀️ 🤦🏾‍♂️ 🤷🏾‍♀️ 🤷🏾‍♂️ 🙎🏾 🙎🏾‍♂️ 🙍🏾 🙍🏾‍♂️ 💇🏾 💇🏾‍♂️ 💆🏾 💆🏾‍♂️ 🕴🏾 💃🏾 🕺🏾 🚶🏾‍♀️ 🚶🏾 🏃🏾‍♀️ 🏃🏾 🤲🏾 👐🏾 🙌🏾 👏🏾 🙏🏾 👍🏾 👎🏾 👊🏾 ✊🏾 🤛🏾 🤜🏾 🤞🏾 ✌🏾 🤟🏾 🤘🏾 👌🏾 👈🏾 👉🏾 👆🏾 👇🏾 ☝🏾 ✋🏾 🤚🏾 🖐🏾 🖖🏾 👋🏾 🤙🏾 💪🏾 🖕🏾 ✍🏾 🤳🏾 💅🏾 👂🏾 👃🏾👶🏿 👦🏿 👧🏿 👨🏿 👩🏿 👱🏿‍♀️ 👱🏿 👴🏿 👵🏿 👲🏿 👳🏿‍♀️ 👳🏿 👮🏿‍♀️ 👮🏿 👷🏿‍♀️ 👷🏿 💂🏿‍♀️ 💂🏿 🕵🏿‍♀️ 🕵🏿 👩🏿‍⚕️ 👨🏿‍⚕️ 👩🏿‍🌾 👨🏿‍🌾 👩🏿‍🍳 👨🏿‍🍳 👩🏿‍🎓 👨🏿‍🎓 👩🏿‍🎤 👨🏿‍🎤 👩🏿‍🏫 👨🏿‍🏫 👩🏿‍🏭 👨🏿‍🏭 👩🏿‍💻 👨🏿‍💻 👩🏿‍💼 👨🏿‍💼 👩🏿‍🔧 👨🏿‍🔧 👩🏿‍🔬 👨🏿‍🔬 👩🏿‍🎨 👨🏿‍🎨 👩🏿‍🚒 👨🏿‍🚒 👩🏿‍✈️ 👨🏿‍✈️ 👩🏿‍🚀 👨🏿‍🚀 👩🏿‍⚖️ 👨🏿‍⚖️ 🤶🏿 🎅🏿 👸🏿 🤴🏿 👰🏿 🤵🏿 👼🏿 🤰🏿 🙇🏿‍♀️ 🙇🏿 💁🏿 💁🏿‍♂️ 🙅🏿 🙅🏿‍♂️ 🙆🏿 🙆🏿‍♂️ 🙋🏿 🙋🏿‍♂️ 🤦🏿‍♀️ 🤦🏿‍♂️ 🤷🏿‍♀️ 🤷🏿‍♂️ 🙎🏿 🙎🏿‍♂️ 🙍🏿 🙍🏿‍♂️ 💇🏿 💇🏿‍♂️ 💆🏿 💆🏿‍♂️ 🕴🏿 💃🏿 🕺🏿 🚶🏿‍♀️ 🚶🏿 🏃🏿‍♀️ 🏃🏿 🤲🏿 👐🏿 🙌🏿 👏🏿 🙏🏿 👍🏿 👎🏿 👊🏿 ✊🏿 🤛🏿 🤜🏿 🤞🏿 ✌🏿 🤟🏿 🤘🏿 👌🏿 👈🏿 👉🏿 👆🏿 👇🏿 ☝🏿 ✋🏿 🤚🏿 🖐🏿 🖖🏿 👋🏿 🤙🏿 💪🏿 🖕🏿 ✍🏿 🤳🏿 💅🏿 👂🏿 👃🏿🐶 🐱 🐭 🐹 🐰 🦊 🦝 🐻 🐼 🦘 🦡 🐨 🐯 🦁 🐮 🐷 🐽 🐸 🐵 🙈 🙉 🙊 🐒 🐔 🐧 🐦 🐤 🐣 🐥 🦆 🦢 🦅 🦉 🦚 🦜 🦇 🐺 🐗 🐴 🦄 🐝 🐛 🦋 🐌 🐚 🐞 🐜 🦗 🕷 🕸 🦂 🦟 🦠 🐢 🐍 🦎 🦖 🦕 🐙 🦑 🦐 🦀 🐡 🐠 🐟 🐬 🐳 🐋 🦈 🐊 🐅 🐆 🦓 🦍 🐘 🦏 🦛 🐪 🐫 🦙 🦒 🐃 🐂 🐄 🐎 🐖 🐏 🐑 🐐 🦌 🐕 🐩 🐈 🐓 🦃 🕊 🐇 🐁 🐀 🐿 🦔 🐾 🐉 🐲 🌵 🎄 🌲 🌳 🌴 🌱 🌿 ☘️ 🍀 🎍 🎋 🍃 🍂 🍁 🍄 🌾 💐 🌷 🌹 🥀 🌺 🌸 🌼 🌻 🌞 🌝 🌛 🌜 🌚 🌕 🌖 🌗 🌘 🌑 🌒 🌓 🌔 🌙 🌎 🌍 🌏 💫 ⭐️ 🌟 ✨ ⚡️ ☄️ 💥 🔥 🌪 🌈 ☀️ 🌤 ⛅️ 🌥 ☁️ 🌦 🌧 ⛈ 🌩 🌨 ❄️ ☃️ ⛄️ 🌬 💨 💧 💦 ☔️ ☂️ 🌊 🌫🍏 🍎 🍐 🍊 🍋 🍌 🍉 🍇 🍓 🍈 🍒 🍑 🍍 🥭 🥥 🥝 🍅 🍆 🥑 🥦 🥒 🥬 🌶 🌽 🥕 🥔 🍠 🥐 🍞 🥖 🥨 🥯 🧀 🥚 🍳 🥞 🥓 🥩 🍗 🍖 🌭 🍔 🍟 🍕 🥪 🥙 🌮 🌯 🥗 🥘 🥫 🍝 🍜 🍲 🍛 🍣 🍱 🥟 🍤 🍙 🍚 🍘 🍥 🥮 🥠 🍢 🍡 🍧 🍨 🍦 🥧 🍰 🎂 🍮 🍭 🍬 🍫 🍿 🧂 🍩 🍪 🌰 🥜 🍯 🥛 🍼 ☕️ 🍵 🥤 🍶 🍺 🍻 🥂 🍷 🥃 🍸 🍹 🍾 🥄 🍴 🍽 🥣 🥡 🥢⚽️ 🏀 🏈 ⚾️ 🥎 🏐 🏉 🎾 🥏 🎱 🏓 🏸 🥅 🏒 🏑 🥍 🏏 ⛳️ 🏹 🎣 🥊 🥋 🎽 ⛸ 🥌 🛷 🛹 🎿 ⛷ 🏂 🏋️‍♀️ 🏋🏻‍♀️ 🏋🏼‍♀️ 🏋🏽‍♀️ 🏋🏾‍♀️ 🏋🏿‍♀️ 🏋️‍♂️ 🏋🏻‍♂️ 🏋🏼‍♂️ 🏋🏽‍♂️ 🏋🏾‍♂️ 🏋🏿‍♂️ 🤼‍♀️ 🤼‍♂️ 🤸‍♀️ 🤸🏻‍♀️ 🤸🏼‍♀️ 🤸🏽‍♀️ 🤸🏾‍♀️ 🤸🏿‍♀️ 🤸‍♂️ 🤸🏻‍♂️ 🤸🏼‍♂️ 🤸🏽‍♂️ 🤸🏾‍♂️ 🤸🏿‍♂️ ⛹️‍♀️ ⛹🏻‍♀️ ⛹🏼‍♀️ ⛹🏽‍♀️ ⛹🏾‍♀️ ⛹🏿‍♀️ ⛹️‍♂️ ⛹🏻‍♂️ ⛹🏼‍♂️ ⛹🏽‍♂️ ⛹🏾‍♂️ ⛹🏿‍♂️ 🤺 🤾‍♀️ 🤾🏻‍♀️ 🤾🏼‍♀️ 🤾🏾‍♀️ 🤾🏾‍♀️ 🤾🏿‍♀️ 🤾‍♂️ 🤾🏻‍♂️ 🤾🏼‍♂️ 🤾🏽‍♂️ 🤾🏾‍♂️ 🤾🏿‍♂️ 🏌️‍♀️ 🏌🏻‍♀️ 🏌🏼‍♀️ 🏌🏽‍♀️ 🏌🏾‍♀️ 🏌🏿‍♀️ 🏌️‍♂️ 🏌🏻‍♂️ 🏌🏼‍♂️ 🏌🏽‍♂️ 🏌🏾‍♂️ 🏌🏿‍♂️ 🏇 🏇🏻 🏇🏼 🏇🏽 🏇🏾 🏇🏿 🧘‍♀️ 🧘🏻‍♀️ 🧘🏼‍♀️ 🧘🏽‍♀️ 🧘🏾‍♀️ 🧘🏿‍♀️ 🧘‍♂️ 🧘🏻‍♂️ 🧘🏼‍♂️ 🧘🏽‍♂️ 🧘🏾‍♂️ 🧘🏿‍♂️ 🏄‍♀️ 🏄🏻‍♀️ 🏄🏼‍♀️ 🏄🏽‍♀️ 🏄🏾‍♀️ 🏄🏿‍♀️ 🏄‍♂️ 🏄🏻‍♂️ 🏄🏼‍♂️ 🏄🏽‍♂️ 🏄🏾‍♂️ 🏄🏿‍♂️ 🏊‍♀️ 🏊🏻‍♀️ 🏊🏼‍♀️ 🏊🏽‍♀️ 🏊🏾‍♀️ 🏊🏿‍♀️ 🏊‍♂️ 🏊🏻‍♂️ 🏊🏼‍♂️ 🏊🏽‍♂️ 🏊🏾‍♂️ 🏊🏿‍♂️ 🤽‍♀️ 🤽🏻‍♀️ 🤽🏼‍♀️ 🤽🏽‍♀️ 🤽🏾‍♀️ 🤽🏿‍♀️ 🤽‍♂️ 🤽🏻‍♂️ 🤽🏼‍♂️ 🤽🏽‍♂️ 🤽🏾‍♂️ 🤽🏿‍♂️ 🚣‍♀️ 🚣🏻‍♀️ 🚣🏼‍♀️ 🚣🏽‍♀️ 🚣🏾‍♀️ 🚣🏿‍♀️ 🚣‍♂️ 🚣🏻‍♂️ 🚣🏼‍♂️ 🚣🏽‍♂️ 🚣🏾‍♂️ 🚣🏿‍♂️ 🧗‍♀️ 🧗🏻‍♀️ 🧗🏼‍♀️ 🧗🏽‍♀️ 🧗🏾‍♀️ 🧗🏿‍♀️ 🧗‍♂️ 🧗🏻‍♂️ 🧗🏼‍♂️ 🧗🏽‍♂️ 🧗🏾‍♂️ 🧗🏿‍♂️ 🚵‍♀️ 🚵🏻‍♀️ 🚵🏼‍♀️ 🚵🏽‍♀️ 🚵🏾‍♀️ 🚵🏿‍♀️ 🚵‍♂️ 🚵🏻‍♂️ 🚵🏼‍♂️ 🚵🏽‍♂️ 🚵🏾‍♂️ 🚵🏿‍♂️ 🚴‍♀️ 🚴🏻‍♀️ 🚴🏼‍♀️ 🚴🏽‍♀️ 🚴🏾‍♀️ 🚴🏿‍♀️ 🚴‍♂️ 🚴🏻‍♂️ 🚴🏼‍♂️ 🚴🏽‍♂️ 🚴🏾‍♂️ 🚴🏿‍♂️ 🏆 🥇 🥈 🥉 🏅 🎖 🏵 🎗 🎫 🎟 🎪 🤹‍♀️ 🤹🏻‍♀️ 🤹🏼‍♀️ 🤹🏽‍♀️ 🤹🏾‍♀️ 🤹🏿‍♀️ 🤹‍♂️ 🤹🏻‍♂️ 🤹🏼‍♂️ 🤹🏽‍♂️ 🤹🏾‍♂️ 🤹🏿‍♂️ 🎭 🎨 🎬 🎤 🎧 🎼 🎹 🥁 🎷 🎺 🎸 🎻 🎲 🧩 ♟ 🎯 🎳 🎮 🎰🚗 🚕 🚙 🚌 🚎 🏎 🚓 🚑 🚒 🚐 🚚 🚛 🚜 🛴 🚲 🛵 🏍 🚨 🚔 🚍 🚘 🚖 🚡 🚠 🚟 🚃 🚋 🚞 🚝 🚄 🚅 🚈 🚂 🚆 🚇 🚊 🚉 ✈️ 🛫 🛬 🛩 💺 🛰 🚀 🛸 🚁 🛶 ⛵️ 🚤 🛥 🛳 ⛴ 🚢 ⚓️ ⛽️ 🚧 🚦 🚥 🚏 🗺 🗿 🗽 🗼 🏰 🏯 🏟 🎡 🎢 🎠 ⛲️ ⛱ 🏖 🏝 🏜 🌋 ⛰ 🏔 🗻 🏕 ⛺️ 🏠 🏡 🏘 🏚 🏗 🏭 🏢 🏬 🏣 🏤 🏥 🏦 🏨 🏪 🏫 🏩 💒 🏛 ⛪️ 🕌 🕍 🕋 ⛩ 🛤 🛣 🗾 🎑 🏞 🌅 🌄 🌠 🎇 🎆 🌇 🌆 🏙 🌃 🌌 🌉 🌁⌚️ 📱 📲 💻 ⌨️ 🖥 🖨 🖱 🖲 🕹 🗜 💽 💾 💿 📀 📼 📷 📸 📹 🎥 📽 🎞 📞 ☎️ 📟 📠 📺 📻 🎙 🎚 🎛 ⏱ ⏲ ⏰ 🕰 ⌛️ ⏳ 📡 🔋 🔌 💡 🔦 🕯 🗑 🛢 💸 💵 💴 💶 💷 💰 💳 🧾 💎 ⚖️ 🔧 🔨 ⚒ 🛠 ⛏ 🔩 ⚙️ ⛓ 🔫 💣 🔪 🗡 ⚔️ 🛡 🚬 ⚰️ ⚱️ 🏺 🧭 🧱 🔮 🧿 🧸 📿 💈 ⚗️ 🔭 🧰 🧲 🧪 🧫 🧬 🧯 🔬 🕳 💊 💉 🌡 🚽 🚰 🚿 🛁 🛀 🛀🏻 🛀🏼 🛀🏽 🛀🏾 🛀🏿 🧴 🧵 🧶 🧷 🧹 🧺 🧻 🧼 🧽 🛎 🔑 🗝 🚪 🛋 🛏 🛌 🖼 🛍 🧳 🛒 🎁 🎈 🎏 🎀 🎊 🎉 🧨 🎎 🏮 🎐 🧧 ✉️ 📩 📨 📧 💌 📥 📤 📦 🏷 📪 📫 📬 📭 📮 📯 📜 📃 📄 📑 📊 📈 📉 🗒 🗓 📆 📅 📇 🗃 🗳 🗄 📋 📁 📂 🗂 🗞 📰 📓 📔 📒 📕 📗 📘 📙 📚 📖 🔖 🔗 📎 🖇 📐 📏 📌 📍 ✂️ 🖊 🖋 ✒️ 🖌 🖍 📝 ✏️ 🔍 🔎 🔏 🔐 🔒 🔓❤️ 🧡 💛 💚 💙 💜 🖤 💔 ❣️ 💕 💞 💓 💗 💖 💘 💝 💟 ☮️ ✝️ ☪️ 🕉 ☸️ ✡️ 🔯 🕎 ☯️ ☦️ 🛐 ⛎ ♈️ ♉️ ♊️ ♋️ ♌️ ♍️ ♎️ ♏️ ♐️ ♑️ ♒️ ♓️ 🆔 ⚛️ 🉑 ☢️ ☣️ 📴 📳 🈶 🈚️ 🈸 🈺 🈷️ ✴️ 🆚 💮 🉐 ㊙️ ㊗️ 🈴 🈵 🈹 🈲 🅰️ 🅱️ 🆎 🆑 🅾️ 🆘 ❌ ⭕️ 🛑 ⛔️ 📛 🚫 💯 💢 ♨️ 🚷 🚯 🚳 🚱 🔞 📵 🚭 ❗️ ❕ ❓ ❔ ‼️ ⁉️ 🔅 🔆 〽️ ⚠️ 🚸 🔱 ⚜️ 🔰 ♻️ ✅ 🈯️ 💹 ❇️ ✳️ ❎ 🌐 💠 Ⓜ️ 🌀 💤 🏧 🚾 ♿️ 🅿️ 🈳 🈂️ 🛂 🛃 🛄 🛅 🚹 🚺 🚼 🚻 🚮 🎦 📶 🈁 🔣 ℹ️ 🔤 🔡 🔠 🆖 🆗 🆙 🆒 🆕 🆓 0️⃣ 1️⃣ 2️⃣ 3️⃣ 4️⃣ 5️⃣ 6️⃣ 7️⃣ 8️⃣ 9️⃣ 🔟 🔢 #️⃣ *️⃣ ⏏️ ▶️ ⏸ ⏯ ⏹ ⏺ ⏭ ⏮ ⏩ ⏪ ⏫ ⏬ ◀️ 🔼 🔽 ➡️ ⬅️ ⬆️ ⬇️ ↗️ ↘️ ↙️ ↖️ ↕️ ↔️ ↪️ ↩️ ⤴️ ⤵️ 🔀 🔁 🔂 🔄 🔃 🎵 🎶 ➕ ➖ ➗ ✖️ ♾ 💲 💱 ™️ ©️ ®️ 〰️ ➰ ➿ 🔚 🔙 🔛 🔝 🔜 ✔️ ☑️ 🔘 ⚪️ ⚫️ 🔴 🔵 🔺 🔻 🔸 🔹 🔶 🔷 🔳 🔲 ▪️ ▫️ ◾️ ◽️ ◼️ ◻️ ⬛️ ⬜️ 🔈 🔇 🔉 🔊 🔔 🔕 📣 📢 👁‍🗨 💬 💭 🗯 ♠️ ♣️ ♥️ ♦️ 🃏 🎴 🀄️ 🕐 🕑 🕒 🕓 🕔 🕕 🕖 🕗 🕘 🕙 🕚 🕛 🕜 🕝 🕞 🕟 🕠 🕡 🕢 🕣 🕤 🕥 🕦 🕧🏳️ 🏴 🏁 🚩 🏳️‍🌈 🏴‍☠️ 🇦🇫 🇦🇽 🇦🇱 🇩🇿 🇦🇸 🇦🇩 🇦🇴 🇦🇮 🇦🇶 🇦🇬 🇦🇷 🇦🇲 🇦🇼 🇦🇺 🇦🇹 🇦🇿 🇧🇸 🇧🇭 🇧🇩 🇧🇧 🇧🇾 🇧🇪 🇧🇿 🇧🇯 🇧🇲 🇧🇹 🇧🇴 🇧🇦 🇧🇼 🇧🇷 🇮🇴 🇻🇬 🇧🇳 🇧🇬 🇧🇫 🇧🇮 🇰🇭 🇨🇲 🇨🇦 🇮🇨 🇨🇻 🇧🇶 🇰🇾 🇨🇫 🇹🇩 🇨🇱 🇨🇳 🇨🇽 🇨🇨 🇨🇴 🇰🇲 🇨🇬 🇨🇩 🇨🇰 🇨🇷 🇨🇮 🇭🇷 🇨🇺 🇨🇼 🇨🇾 🇨🇿 🇩🇰 🇩🇯 🇩🇲 🇩🇴 🇪🇨 🇪🇬 🇸🇻 🇬🇶 🇪🇷 🇪🇪 🇪🇹 🇪🇺 🇫🇰 🇫🇴 🇫🇯 🇫🇮 🇫🇷 🇬🇫 🇵🇫 🇹🇫 🇬🇦 🇬🇲 🇬🇪 🇩🇪 🇬🇭 🇬🇮 🇬🇷 🇬🇱 🇬🇩 🇬🇵 🇬🇺 🇬🇹 🇬🇬 🇬🇳 🇬🇼 🇬🇾 🇭🇹 🇭🇳 🇭🇰 🇭🇺 🇮🇸 🇮🇳 🇮🇩 🇮🇷 🇮🇶 🇮🇪 🇮🇲 🇮🇱 🇮🇹 🇯🇲 🇯🇵 🎌 🇯🇪 🇯🇴 🇰🇿 🇰🇪 🇰🇮 🇽🇰 🇰🇼 🇰🇬 🇱🇦 🇱🇻 🇱🇧 🇱🇸 🇱🇷 🇱🇾 🇱🇮 🇱🇹 🇱🇺 🇲🇴 🇲🇰 🇲🇬 🇲🇼 🇲🇾 🇲🇻 🇲🇱 🇲🇹 🇲🇭 🇲🇶 🇲🇷 🇲🇺 🇾🇹 🇲🇽 🇫🇲 🇲🇩 🇲🇨 🇲🇳 🇲🇪 🇲🇸 🇲🇦 🇲🇿 🇲🇲 🇳🇦 🇳🇷 🇳🇵 🇳🇱 🇳🇨 🇳🇿 🇳🇮 🇳🇪 🇳🇬 🇳🇺 🇳🇫 🇰🇵 🇲🇵 🇳🇴 🇴🇲 🇵🇰 🇵🇼 🇵🇸 🇵🇦 🇵🇬 🇵🇾 🇵🇪 🇵🇭 🇵🇳 🇵🇱 🇵🇹 🇵🇷 🇶🇦 🇷🇪 🇷🇴 🇷🇺 🇷🇼 🇼🇸 🇸🇲 🇸🇦 🇸🇳 🇷🇸 🇸🇨 🇸🇱 🇸🇬 🇸🇽 🇸🇰 🇸🇮 🇬🇸 🇸🇧 🇸🇴 🇿🇦 🇰🇷 🇸🇸 🇪🇸 🇱🇰 🇧🇱 🇸🇭 🇰🇳 🇱🇨 🇵🇲 🇻🇨 🇸🇩 🇸🇷 🇸🇿 🇸🇪 🇨🇭 🇸🇾 🇹🇼 🇹🇯 🇹🇿 🇹🇭 🇹🇱 🇹🇬 🇹🇰 🇹🇴 🇹🇹 🇹🇳 🇹🇷 🇹🇲 🇹🇨 🇹🇻 🇻🇮 🇺🇬 🇺🇦 🇦🇪 🇬🇧 🏴󠁧󠁢󠁥󠁮󠁧󠁿 🏴󠁧󠁢󠁳󠁣󠁴󠁿 🏴󠁧󠁢󠁷󠁬󠁳󠁿 🇺🇳 🇺🇸 🇺🇾 🇺🇿 🇻🇺 🇻🇦 🇻🇪 🇻🇳 🇼🇫 🇪🇭 🇾🇪 🇿🇲 🇿🇼🥱 🤏 🦾 🦿 🦻 🧏 🧏‍♂️ 🧏‍♀️ 🧍 🧍‍♂️ 🧍‍♀️ 🧎 🧎‍♂️ 🧎‍♀️ 👨‍🦯 👩‍🦯 👨‍🦼 👩‍🦼 👨‍🦽 👩‍🦽 🦧 🦮 🐕‍🦺 🦥 🦦 🦨 🦩 🧄 🧅 🧇 🧆 🧈 🦪 🧃 🧉 🧊 🛕 🦽 🦼 🛺 🪂 🪐 🤿 🪀 🪁 🦺 🥻 🩱 🩲 🩳 🩰 🪕 🪔 🪓 🦯 🩸 🩹 🩺 🪑 🪒 🤎 🤍 🟠 🟡 🟢 🟣 🟤 🟥 🟧 🟨 🟩 🟦 🟪 🟫 + + diff --git a/tests/backend/specs/api/instance.js b/tests/backend/specs/api/instance.js new file mode 100644 index 00000000000..4849c6507af --- /dev/null +++ b/tests/backend/specs/api/instance.js @@ -0,0 +1,54 @@ +/* + * Tests for the instance-level APIs + * + * Section "GLOBAL FUNCTIONS" in src/node/db/API.js + */ +const assert = require('assert'); +const supertest = require(__dirname+'/../../../../src/node_modules/supertest'); +const fs = require('fs'); +const settings = require(__dirname+'/../../../../src/node/utils/Settings'); +const api = supertest('http://'+settings.ip+":"+settings.port); +const path = require('path'); + +var filePath = path.join(__dirname, '../../../../APIKEY.txt'); + +var apiKey = fs.readFileSync(filePath, {encoding: 'utf-8'}); +apiKey = apiKey.replace(/\n$/, ""); + +var apiVersion = '1.2.14'; + +describe('Connectivity for instance-level API tests', function() { + it('can connect', function(done) { + api.get('/api/') + .expect('Content-Type', /json/) + .expect(200, done) + }); +}); + +describe('getStats', function(){ + it('Gets the stats of a running instance', function(done) { + api.get(endPoint('getStats')) + .expect(function(res){ + if (res.body.code !== 0) throw new Error("getStats() failed"); + + if (!(('totalPads' in res.body.data) && (typeof res.body.data.totalPads === 'number'))) { + throw new Error(`Response to getStats() does not contain field totalPads, or it's not a number: ${JSON.stringify(res.body.data)}`); + } + + if (!(('totalSessions' in res.body.data) && (typeof res.body.data.totalSessions === 'number'))) { + throw new Error(`Response to getStats() does not contain field totalSessions, or it's not a number: ${JSON.stringify(res.body.data)}`); + } + + if (!(('totalActivePads' in res.body.data) && (typeof res.body.data.totalActivePads === 'number'))) { + throw new Error(`Response to getStats() does not contain field totalActivePads, or it's not a number: ${JSON.stringify(res.body.data)}`); + } + }) + .expect('Content-Type', /json/) + .expect(200, done); + }); +}); + +var endPoint = function(point, version){ + version = version || apiVersion; + return '/api/'+version+'/'+point+'?apikey='+apiKey; +} diff --git a/tests/backend/specs/api/pad.js b/tests/backend/specs/api/pad.js index 4a0c6b6a216..c1b8d49df17 100644 --- a/tests/backend/specs/api/pad.js +++ b/tests/backend/specs/api/pad.js @@ -1,10 +1,17 @@ -var assert = require('assert') - supertest = require(__dirname+'/../../../../src/node_modules/supertest'), - fs = require('fs'), - settings = require(__dirname+'/../../loadSettings').loadSettings(), - api = supertest('http://'+settings.ip+":"+settings.port), - path = require('path'), - async = require(__dirname+'/../../../../src/node_modules/async'); +/* + * ACHTUNG: there is a copied & modified version of this file in + * /tests/container/specs/api/pad.js + * + * TODO: unify those two files, and merge in a single one. + */ + +const assert = require('assert'); +const supertest = require(__dirname+'/../../../../src/node_modules/supertest'); +const fs = require('fs'); +const settings = require(__dirname + '/../../../../src/node/utils/Settings'); +const api = supertest('http://'+settings.ip+":"+settings.port); +const path = require('path'); +const async = require(__dirname+'/../../../../src/node_modules/async'); var filePath = path.join(__dirname, '../../../../APIKEY.txt'); @@ -29,7 +36,7 @@ var ulHtml = '
      • one
      • two< var expectedHtml = '
        • one
        • two
        • 0
        • 1
        • 2
          • 3
          • 4
        1. item
          1. item1
          2. item2
        '; describe('Connectivity', function(){ - it('errors if can not connect', function(done) { + it('can connect', function(done) { api.get('/api/') .expect('Content-Type', /json/) .expect(200, done) @@ -37,7 +44,7 @@ describe('Connectivity', function(){ }) describe('API Versioning', function(){ - it('errors if can not connect', function(done) { + it('finds the version tag', function(done) { api.get('/api/') .expect(function(res){ apiVersion = res.body.currentVersion; @@ -49,7 +56,7 @@ describe('API Versioning', function(){ }) describe('Permission', function(){ - it('errors if can connect without correct APIKey', function(done) { + it('errors with invalid APIKey', function(done) { // This is broken because Etherpad doesn't handle HTTP codes properly see #2343 // If your APIKey is password you deserve to fail all tests anyway var permErrorURL = '/api/'+apiVersion+'/createPad?apikey=password&padID=test'; @@ -104,7 +111,7 @@ describe('deletePad', function(){ it('deletes a Pad', function(done) { api.get(endPoint('deletePad')+"&padID="+testPadId) .expect('Content-Type', /json/) - .expect(200, done) + .expect(200, done) // @TODO: we shouldn't expect 200 here since the pad may not exist }); }) @@ -166,6 +173,19 @@ describe('getHTML', function(){ }); }) +describe('listAllPads', function () { + it('list all pads', function (done) { + api.get(endPoint('listAllPads')) + .expect(function (res) { + if (res.body.data.padIDs.includes(testPadId) !== true) { + throw new Error('Unable to find pad in pad list') + } + }) + .expect('Content-Type', /json/) + .expect(200, done) + }) +}) + describe('deletePad', function(){ it('deletes a Pad', function(done) { api.get(endPoint('deletePad')+"&padID="+testPadId) @@ -177,6 +197,19 @@ describe('deletePad', function(){ }); }) +describe('listAllPads', function () { + it('list all pads', function (done) { + api.get(endPoint('listAllPads')) + .expect(function (res) { + if (res.body.data.padIDs.includes(testPadId) !== false) { + throw new Error('Test pad should not be in pads list') + } + }) + .expect('Content-Type', /json/) + .expect(200, done) + }) +}) + describe('getHTML', function(){ it('get the HTML of a Pad -- Should return a failure', function(done) { api.get(endPoint('getHTML')+"&padID="+testPadId) @@ -204,7 +237,7 @@ describe('getText', function(){ api.get(endPoint('getText')+"&padID="+testPadId) .expect(function(res){ if(res.body.data.text !== "testText\n") throw new Error("Pad Creation with text") - }) + }) .expect('Content-Type', /json/) .expect(200, done) }); @@ -212,7 +245,11 @@ describe('getText', function(){ describe('setText', function(){ it('creates a new Pad with text', function(done) { - api.get(endPoint('setText')+"&padID="+testPadId+"&text=testTextTwo") + api.post(endPoint('setText')) + .send({ + "padID": testPadId, + "text": "testTextTwo", + }) .expect(function(res){ if(res.body.code !== 0) throw new Error("Pad setting text failed"); }) @@ -327,7 +364,11 @@ describe('getLastEdited', function(){ describe('setText', function(){ it('creates a new Pad with text', function(done) { - api.get(endPoint('setText')+"&padID="+testPadId+"&text=testTextTwo") + api.post(endPoint('setText')) + .send({ + "padID": testPadId, + "text": "testTextTwo", + }) .expect(function(res){ if(res.body.code !== 0) throw new Error("Pad setting text failed"); }) @@ -388,7 +429,7 @@ describe('createPad', function(){ describe('setText', function(){ it('Sets text on a pad Id', function(done) { api.post(endPoint('setText')+"&padID="+testPadId) - .send({text: text}) + .field({text: text}) .expect(function(res){ if(res.body.code !== 0) throw new Error("Pad Set Text failed") }) @@ -412,7 +453,7 @@ describe('getText', function(){ describe('setText', function(){ it('Sets text on a pad Id including an explicit newline', function(done) { api.post(endPoint('setText')+"&padID="+testPadId) - .send({text: text+'\n'}) + .field({text: text+'\n'}) .expect(function(res){ if(res.body.code !== 0) throw new Error("Pad Set Text failed") }) @@ -526,7 +567,11 @@ describe('getText', function(){ describe('setHTML', function(){ it('Sets the HTML of a Pad attempting to pass ugly HTML', function(done) { var html = "
        Hello HTML
        "; - api.get(endPoint('setHTML')+"&padID="+testPadId+"&html="+html) + api.post(endPoint('setHTML')) + .send({ + "padID": testPadId, + "html": html, + }) .expect(function(res){ if(res.body.code !== 1) throw new Error("Allowing crappy HTML to be imported") }) @@ -537,7 +582,11 @@ describe('setHTML', function(){ describe('setHTML', function(){ it('Sets the HTML of a Pad with complex nested lists of different types', function(done) { - api.get(endPoint('setHTML')+"&padID="+testPadId+"&html="+ulHtml) + api.post(endPoint('setHTML')) + .send({ + "padID": testPadId, + "html": ulHtml, + }) .expect(function(res){ if(res.body.code !== 0) throw new Error("List HTML cant be imported") }) @@ -573,7 +622,7 @@ describe('createPad', function(){ it('errors if pad can be created', function(done) { var badUrlChars = ["/", "%23", "%3F", "%26"]; async.map( - badUrlChars, + badUrlChars, function (badUrlChar, cb) { api.get(endPoint('createPad')+"&padID="+badUrlChar) .expect(function(res){ diff --git a/tests/backend/specs/api/sessionsAndGroups.js b/tests/backend/specs/api/sessionsAndGroups.js index 961cb2df9a4..cbc6e0a1abf 100644 --- a/tests/backend/specs/api/sessionsAndGroups.js +++ b/tests/backend/specs/api/sessionsAndGroups.js @@ -1,7 +1,7 @@ var assert = require('assert') supertest = require(__dirname+'/../../../../src/node_modules/supertest'), fs = require('fs'), - settings = require(__dirname+'/../../loadSettings').loadSettings(), + settings = require(__dirname + '/../../../../src/node/utils/Settings'), api = supertest('http://'+settings.ip+":"+settings.port), path = require('path'); diff --git a/tests/container/loadSettings.js b/tests/container/loadSettings.js new file mode 100644 index 00000000000..4a1c46021ef --- /dev/null +++ b/tests/container/loadSettings.js @@ -0,0 +1,37 @@ +/* + * ACHTUNG: this file is a hack used to load "settings.json.docker" instead of + * "settings.json", since in its present form the Settings module does + * not allow it. + * This is a remnant of an analogous file that was placed in + * /tests/backend/loadSettings.js + * + * TODO: modify the Settings module: + * 1) no side effects on module load + * 2) write a factory method that loads a configuration file (taking the + * file name from the command line, a function argument, or falling + * back to a default) + */ + +var jsonminify = require(__dirname+"/../../src/node_modules/jsonminify"); +const fs = require('fs'); + +function loadSettings(){ + var settingsStr = fs.readFileSync(__dirname+"/../../settings.json.docker").toString(); + // try to parse the settings + try { + if(settingsStr) { + settingsStr = jsonminify(settingsStr).replace(",]","]").replace(",}","}"); + var settings = JSON.parse(settingsStr); + + // custom settings for running in a container + settings.ip = 'localhost'; + settings.port = '9001'; + + return settings; + } + }catch(e){ + console.error("whoops something is bad with settings"); + } +} + +exports.loadSettings = loadSettings; diff --git a/tests/container/specs/api/pad.js b/tests/container/specs/api/pad.js new file mode 100644 index 00000000000..f50b7986468 --- /dev/null +++ b/tests/container/specs/api/pad.js @@ -0,0 +1,38 @@ +/* + * ACHTUNG: this file was copied & modified from the analogous + * /tests/backend/specs/api/pad.js + * + * TODO: unify those two files, and merge in a single one. + */ + +const supertest = require(__dirname+'/../../../../src/node_modules/supertest'); +const settings = require(__dirname+'/../../loadSettings').loadSettings(); +const api = supertest('http://'+settings.ip+":"+settings.port); + +var apiVersion = 1; + +describe('Connectivity', function(){ + it('can connect', function(done) { + api.get('/api/') + .expect('Content-Type', /json/) + .expect(200, done) + }); +}) + +describe('API Versioning', function(){ + it('finds the version tag', function(done) { + api.get('/api/') + .expect(function(res){ + if (!res.body.currentVersion) throw new Error("No version set in API"); + return; + }) + .expect(200, done) + }); +}) + +describe('Permission', function(){ + it('errors with invalid APIKey', function(done) { + api.get('/api/'+apiVersion+'/createPad?apikey=wrong_password&padID=test') + .expect(401, done) + }); +}) diff --git a/tests/frontend/helper.js b/tests/frontend/helper.js index 7a8d19b6029..800dfb29315 100644 --- a/tests/frontend/helper.js +++ b/tests/frontend/helper.js @@ -56,6 +56,22 @@ var helper = {}; window.document.cookie = ""; } + // Functionality for knowing what key event type is required for tests + var evtType = "keydown"; + // if it's IE require keypress + if(window.navigator.userAgent.indexOf("MSIE") > -1){ + evtType = "keypress"; + } + // Edge also requires keypress. + if(window.navigator.userAgent.indexOf("Edge") > -1){ + evtType = "keypress"; + } + // Opera also requires keypress. + if(window.navigator.userAgent.indexOf("OPR") > -1){ + evtType = "keypress"; + } + helper.evtType = evtType; + helper.newPad = function(cb, padName){ //build opts object var opts = {clearCookies: true} @@ -216,4 +232,4 @@ var helper = {}; _it(name, func); } -})() \ No newline at end of file +})() diff --git a/tests/frontend/lib/expect.js b/tests/frontend/lib/expect.js index ab5a1eea30f..c647cf2be06 100644 --- a/tests/frontend/lib/expect.js +++ b/tests/frontend/lib/expect.js @@ -65,7 +65,7 @@ var name = $flags[i] , assertion = new Assertion(this.obj, name, this) - + if ('function' == typeof Assertion.prototype[name]) { // clone the function, make sure we dont touch the prot reference var old = this[name]; @@ -148,7 +148,7 @@ if ('object' == typeof fn && not) { // in the presence of a matcher, ensure the `not` only applies to // the matching. - this.flags.not = false; + this.flags.not = false; } var name = this.obj.name || 'fn'; @@ -219,7 +219,7 @@ }; /** - * Assert within start to finish (inclusive). + * Assert within start to finish (inclusive). * * @param {Number} start * @param {Number} finish @@ -298,7 +298,7 @@ , function(){ return 'expected ' + i(this.obj) + ' to be above ' + n }); return this; }; - + /** * Assert string value matches _regexp_. * @@ -359,13 +359,13 @@ } catch (e) { hasProp = undefined !== this.obj[name] } - + this.assert( hasProp , function(){ return 'expected ' + i(this.obj) + ' to have a property ' + i(name) } , function(){ return 'expected ' + i(this.obj) + ' to not have a property ' + i(name) }); } - + if (undefined !== val) { this.assert( val === this.obj[name] @@ -537,7 +537,7 @@ return html; } }; - + // Returns true if object is a DOM element. var isDOMElement = function (object) { if (typeof HTMLElement === 'object') { @@ -843,9 +843,9 @@ expect.eql = function eql (actual, expected) { // 7.1. All identical values are equivalent, as determined by ===. - if (actual === expected) { + if (actual === expected) { return true; - } else if ('undefined' != typeof Buffer + } else if ('undefined' != typeof Buffer && Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) { if (actual.length != expected.length) return false; diff --git a/tests/frontend/lib/mocha.js b/tests/frontend/lib/mocha.js index 5f2da01399e..0b1e894866e 100644 --- a/tests/frontend/lib/mocha.js +++ b/tests/frontend/lib/mocha.js @@ -32,11 +32,11 @@ require.register = function (path, fn){ require.relative = function (parent) { return function(p){ if ('.' != p.charAt(0)) return require(p); - + var path = parent.split('/') , segs = p.split('/'); path.pop(); - + for (var i = 0; i < segs.length; i++) { var seg = segs[i]; if ('..' == seg) path.pop(); @@ -52,7 +52,7 @@ require.register("browser/debug.js", function(module, exports, require){ module.exports = function(type){ return function(){ - + } }; }); // module: browser/debug.js @@ -530,7 +530,7 @@ var Suite = require('../suite') /** * BDD-style interface: - * + * * describe('Array', function(){ * describe('#indexOf()', function(){ * it('should return -1 when not present', function(){ @@ -542,7 +542,7 @@ var Suite = require('../suite') * }); * }); * }); - * + * */ module.exports = function(suite){ @@ -587,7 +587,7 @@ module.exports = function(suite){ * and callback `fn` containing nested suites * and/or tests. */ - + context.describe = context.context = function(title, fn){ var suite = Suite.create(suites[0], title); suites.unshift(suite); @@ -667,19 +667,19 @@ var Suite = require('../suite') /** * TDD-style interface: - * + * * exports.Array = { * '#indexOf()': { * 'should return -1 when the value is not present': function(){ - * + * * }, * * 'should return the correct index when the value is present': function(){ - * + * * } * } * }; - * + * */ module.exports = function(suite){ @@ -739,27 +739,27 @@ var Suite = require('../suite') /** * QUnit-style interface: - * + * * suite('Array'); - * + * * test('#length', function(){ * var arr = [1,2,3]; * ok(arr.length == 3); * }); - * + * * test('#indexOf()', function(){ * var arr = [1,2,3]; * ok(arr.indexOf(1) == 0); * ok(arr.indexOf(2) == 1); * ok(arr.indexOf(3) == 2); * }); - * + * * suite('String'); - * + * * test('#length', function(){ * ok('foo'.length == 3); * }); - * + * */ module.exports = function(suite){ @@ -802,7 +802,7 @@ module.exports = function(suite){ /** * Describe a "suite" with the given `title`. */ - + context.suite = function(title){ if (suites.length > 1) suites.shift(); var suite = Suite.create(suites[0], title); @@ -840,7 +840,7 @@ var Suite = require('../suite') * suiteSetup(function(){ * * }); - * + * * test('should return -1 when not present', function(){ * * }); @@ -2689,7 +2689,7 @@ exports = module.exports = Min; function Min(runner) { Base.call(this, runner); - + runner.on('start', function(){ // clear screen process.stdout.write('\u001b[2J'); @@ -3337,7 +3337,7 @@ function XUnit(runner) { runner.on('pass', function(test){ tests.push(test); }); - + runner.on('fail', function(test){ tests.push(test); }); @@ -3354,7 +3354,7 @@ function XUnit(runner) { }, false)); tests.forEach(test); - console.log(''); + console.log(''); }); } @@ -3615,7 +3615,7 @@ Runnable.prototype.run = function(fn){ } return; } - + // sync try { if (!this.pending) this.fn.call(ctx); @@ -4536,7 +4536,7 @@ exports.indexOf = function(arr, obj, start){ /** * Array#reduce (<=IE8) - * + * * @param {Array} array * @param {Function} fn * @param {Object} initial value diff --git a/tests/frontend/lib/sendkeys.js b/tests/frontend/lib/sendkeys.js index b57618476a9..7550df38f53 100644 --- a/tests/frontend/lib/sendkeys.js +++ b/tests/frontend/lib/sendkeys.js @@ -305,11 +305,11 @@ var START_TO_END = 1; var END_TO_END = 2; var END_TO_START = 3; // from the Mozilla documentation, for range.compareBoundaryPoints(how, sourceRange) -// -1, 0, or 1, indicating whether the corresponding boundary-point of range is respectively before, equal to, or after the corresponding boundary-point of sourceRange. +// -1, 0, or 1, indicating whether the corresponding boundary-point of range is respectively before, equal to, or after the corresponding boundary-point of sourceRange. // * Range.END_TO_END compares the end boundary-point of sourceRange to the end boundary-point of range. // * Range.END_TO_START compares the end boundary-point of sourceRange to the start boundary-point of range. // * Range.START_TO_END compares the start boundary-point of sourceRange to the end boundary-point of range. - // * Range.START_TO_START compares the start boundary-point of sourceRange to the start boundary-point of range. + // * Range.START_TO_START compares the start boundary-point of sourceRange to the start boundary-point of range. function w3cstart(rng, constraint){ if (rng.compareBoundaryPoints (START_TO_START, constraint) <= 0) return 0; // at or before the beginning if (rng.compareBoundaryPoints (END_TO_START, constraint) >= 0) return constraint.toString().length; diff --git a/tests/frontend/runner.css b/tests/frontend/runner.css index ce158b818ea..66d3283ca3e 100644 --- a/tests/frontend/runner.css +++ b/tests/frontend/runner.css @@ -6,6 +6,9 @@ body { padding: 0px; margin: 0px; height: 100%; + display: flex; + flex-direction: row; + overflow: hidden; } #console { @@ -14,33 +17,30 @@ body { #iframe-container { width: 50%; + min-width: 820px; height: 100%; } #iframe-container iframe { height: 100%; - position:absolute; - min-width:500px; - max-width:800px; - left:50%; width:100%; } #mocha { font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; border-right: 2px solid #999; - width: 50%; + flex: 1 auto; height: 100%; - position: absolute; overflow: auto; - float:left; } #mocha #report { - margin-top: 50px; + margin: 0; + padding: 0; + margin-top: 10px; } -#mocha ul, #mocha li { +#mocha li { margin: 0; padding: 0; } @@ -175,6 +175,10 @@ body { -webkit-box-shadow: 0 1px 3px #eee; } +#report ul { + padding: 0; +} + #report.pass .test.fail { display: none; } @@ -191,12 +195,11 @@ body { } #stats { - position: fixed; - top: 15px; - right: 52%; + padding: 10px; font-size: 12px; margin: 0; color: #888; + text-align: right; } #stats .progress { diff --git a/tests/frontend/runner.js b/tests/frontend/runner.js index e77f6707fd9..1d3ef64150f 100644 --- a/tests/frontend/runner.js +++ b/tests/frontend/runner.js @@ -52,7 +52,7 @@ $(function(){ } /* - This reporter wraps the original html reporter plus reports plain text into a hidden div. + This reporter wraps the original html reporter plus reports plain text into a hidden div. This allows the webdriver client to pick up the test results */ var WebdriverAndHtmlReporter = function(html_reporter){ @@ -170,7 +170,7 @@ $(function(){ //get the list of specs and filter it if requested var specs = specs_list.slice(); - + //inject spec scripts into the dom var $body = $('body'); $.each(specs, function(i, spec){ @@ -195,4 +195,4 @@ $(function(){ mocha.run(); }); -}); +}); diff --git a/tests/frontend/specs/alphabet.js b/tests/frontend/specs/alphabet.js index ae9570e41c4..5d16c983a30 100644 --- a/tests/frontend/specs/alphabet.js +++ b/tests/frontend/specs/alphabet.js @@ -8,12 +8,12 @@ describe("All the alphabet works n stuff", function(){ }); it("when you enter any char it appears right", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; + //get the first text element out of the inner iframe var firstTextElement = inner$("div").first(); - + // simulate key presses to delete content firstTextElement.sendkeys('{selectall}'); // select all firstTextElement.sendkeys('{del}'); // clear the first line diff --git a/tests/frontend/specs/bold.js b/tests/frontend/specs/bold.js index 888eb660258..94e3a9b5b89 100644 --- a/tests/frontend/specs/bold.js +++ b/tests/frontend/specs/bold.js @@ -6,22 +6,22 @@ describe("bold button", function(){ }); it("makes text bold on click", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; //get the first text element out of the inner iframe var $firstTextElement = inner$("div").first(); - + //select this text element $firstTextElement.sendkeys('{selectall}'); //get the bold button and click it var $boldButton = chrome$(".buttonicon-bold"); $boldButton.click(); - + //ace creates a new dom element when you press a button, so just get the first text element again var $newFirstTextElement = inner$("div").first(); - + // is there a element now? var isBold = $newFirstTextElement.find("b").length === 1; @@ -44,13 +44,7 @@ describe("bold button", function(){ //select this text element $firstTextElement.sendkeys('{selectall}'); - if(inner$(window)[0].bowser.modernIE){ // if it's IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - - var e = inner$.Event(evtType); + var e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = 66; // b inner$("#innerdocbody").trigger(e); diff --git a/tests/frontend/specs/caret.js b/tests/frontend/specs/caret.js index 14ff8d6a6da..45c2eb3bec2 100644 --- a/tests/frontend/specs/caret.js +++ b/tests/frontend/specs/caret.js @@ -198,9 +198,9 @@ console.log(inner$); /* it("Creates N rows, changes height of rows, updates UI by caret key events", function(done){ var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + var chrome$ = helper.padChrome$; var numberOfRows = 50; - + //ace creates a new dom element when you press a keystroke, so just get the first text element again var $newFirstTextElement = inner$("div").first(); var originalDivHeight = inner$("div").first().css("height"); @@ -211,7 +211,7 @@ console.log(inner$); }).done(function(){ // Once the DOM has registered the items inner$("div").each(function(index){ // Randomize the item heights (replicates images / headings etc) var random = Math.floor(Math.random() * (50)) + 20; - $(this).css("height", random+"px"); + $(this).css("height", random+"px"); }); console.log(caretPosition(inner$)); @@ -253,7 +253,7 @@ console.log(inner$); keyEvent(inner$, 33, false, false); // doesn't work i++; } - + // Does scrolling back up the pad with the up arrow show the correct contents? helper.waitFor(function(){ // Wait for the new position to be in place try{ @@ -280,7 +280,7 @@ console.log(inner$); helper.waitFor(function(){ // Wait for the new position to be in place return isScrolledIntoView(inner$("div:nth-child(1)"), inner$); // Wait for the DOM to scroll into place }).done(function(){ // Once the DOM has registered the items - expect(true).to.be(true); + expect(true).to.be(true); done(); }); */ @@ -297,20 +297,15 @@ function prepareDocument(n, target){ // generates a random document with random } function keyEvent(target, charCode, ctrl, shift){ // sends a charCode to the window - if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - var e = target.Event(evtType); - console.log(e); + + var e = target.Event(helper.evtType); if(ctrl){ e.ctrlKey = true; // Control key } if(shift){ e.shiftKey = true; // Shift Key } - e.which = charCode; + e.which = charCode; e.keyCode = charCode; target("#innerdocbody").trigger(e); } diff --git a/tests/frontend/specs/change_user_color.js b/tests/frontend/specs/change_user_color.js new file mode 100644 index 00000000000..5969eabe298 --- /dev/null +++ b/tests/frontend/specs/change_user_color.js @@ -0,0 +1,104 @@ +describe("change user color", function(){ + //create a new pad before each test run + beforeEach(function(cb){ + helper.newPad(cb); + this.timeout(60000); + }); + + it("Color picker matches original color and remembers the user color after a refresh", function(done) { + this.timeout(60000); + var chrome$ = helper.padChrome$; + + //click on the settings button to make settings visible + var $userButton = chrome$(".buttonicon-showusers"); + $userButton.click(); + + var $userSwatch = chrome$("#myswatch"); + $userSwatch.click(); + + var fb = chrome$.farbtastic('#colorpicker') + var $colorPickerSave = chrome$("#mycolorpickersave"); + var $colorPickerPreview = chrome$("#mycolorpickerpreview"); + + // Same color represented in two different ways + const testColorHash = '#abcdef' + const testColorRGB = 'rgb(171, 205, 239)' + + // Check that the color picker matches the automatically assigned random color on the swatch. + // NOTE: This has a tiny chance of creating a false positive for passing in the + // off-chance the randomly assigned color is the same as the test color. + expect($colorPickerPreview.css('background-color')).to.be($userSwatch.css('background-color')) + + // The swatch updates as the test color is picked. + fb.setColor(testColorHash) + expect($colorPickerPreview.css('background-color')).to.be(testColorRGB) + $colorPickerSave.click(); + expect($userSwatch.css('background-color')).to.be(testColorRGB) + + setTimeout(function(){ //give it a second to save the color on the server side + helper.newPad({ // get a new pad, but don't clear the cookies + clearCookies: false + , cb: function(){ + var chrome$ = helper.padChrome$; + + //click on the settings button to make settings visible + var $userButton = chrome$(".buttonicon-showusers"); + $userButton.click(); + + var $userSwatch = chrome$("#myswatch"); + $userSwatch.click(); + + var $colorPickerPreview = chrome$("#mycolorpickerpreview"); + + expect($colorPickerPreview.css('background-color')).to.be(testColorRGB) + expect($userSwatch.css('background-color')).to.be(testColorRGB) + + done(); + } + }); + }, 1000); + }); + + it("Own user color is shown when you enter a chat", function(done) { + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; + + var $colorOption = helper.padChrome$('#options-colorscheck'); + if (!$colorOption.is(':checked')) { + $colorOption.click(); + } + + //click on the settings button to make settings visible + var $userButton = chrome$(".buttonicon-showusers"); + $userButton.click(); + + var $userSwatch = chrome$("#myswatch"); + $userSwatch.click(); + + var fb = chrome$.farbtastic('#colorpicker') + var $colorPickerSave = chrome$("#mycolorpickersave"); + + // Same color represented in two different ways + const testColorHash = '#abcdef' + const testColorRGB = 'rgb(171, 205, 239)' + + fb.setColor(testColorHash) + $colorPickerSave.click(); + + //click on the chat button to make chat visible + var $chatButton = chrome$("#chaticon"); + $chatButton.click(); + var $chatInput = chrome$("#chatinput"); + $chatInput.sendkeys('O hi'); // simulate a keypress of typing user + $chatInput.sendkeys('{enter}'); // simulate a keypress of enter actually does evt.which = 10 not 13 + + //check if chat shows up + helper.waitFor(function(){ + return chrome$("#chattext").children("p").length !== 0; // wait until the chat message shows up + }).done(function(){ + var $firstChatMessage = chrome$("#chattext").children("p"); + expect($firstChatMessage.css('background-color')).to.be(testColorRGB); // expect the first chat message to be of the user's color + done(); + }); + }); +}); diff --git a/tests/frontend/specs/change_user_name.js b/tests/frontend/specs/change_user_name.js index ba089c90b10..b0a5df15f27 100644 --- a/tests/frontend/specs/change_user_name.js +++ b/tests/frontend/specs/change_user_name.js @@ -12,7 +12,7 @@ describe("change username value", function(){ //click on the settings button to make settings visible var $userButton = chrome$(".buttonicon-showusers"); $userButton.click(); - + var $usernameInput = chrome$("#myusernameedit"); $usernameInput.click(); @@ -45,7 +45,7 @@ describe("change username value", function(){ //click on the settings button to make settings visible var $userButton = chrome$(".buttonicon-showusers"); $userButton.click(); - + var $usernameInput = chrome$("#myusernameedit"); $usernameInput.click(); diff --git a/tests/frontend/specs/chat.js b/tests/frontend/specs/chat.js index 7ebb76fb305..8eaf08a9514 100644 --- a/tests/frontend/specs/chat.js +++ b/tests/frontend/specs/chat.js @@ -6,8 +6,8 @@ describe("Chat messages and UI", function(){ }); it("opens chat, sends a message and makes sure it exists on the page", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; var chatValue = "JohnMcLear"; //click on the chat button to make chat visible @@ -39,8 +39,8 @@ describe("Chat messages and UI", function(){ }); it("makes sure that an empty message can't be sent", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; //click on the chat button to make chat visible var $chatButton = chrome$("#chaticon"); @@ -65,8 +65,8 @@ describe("Chat messages and UI", function(){ }); it("makes chat stick to right side of the screen", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; //click on the settings button to make settings visible var $settingsButton = chrome$(".buttonicon-settings"); @@ -75,56 +75,60 @@ describe("Chat messages and UI", function(){ //get the chat selector var $stickychatCheckbox = chrome$("#options-stickychat"); - //select chat always on screen and fire change event - $stickychatCheckbox.attr('selected','selected'); - $stickychatCheckbox.change(); - $stickychatCheckbox.click(); + //select chat always on screen + if (!$stickychatCheckbox.is(':checked')) { + $stickychatCheckbox.click(); + } - //check if chat changed to get the stickychat Class - var $chatbox = chrome$("#chatbox"); - var hasStickyChatClass = $chatbox.hasClass("stickyChat"); - expect(hasStickyChatClass).to.be(true); + // due to animation, we need to make some timeout... + setTimeout(function() { + //check if chat changed to get the stickychat Class + var $chatbox = chrome$("#chatbox"); + var hasStickyChatClass = $chatbox.hasClass("stickyChat"); + expect(hasStickyChatClass).to.be(true); - //select chat always on screen and fire change event - $stickychatCheckbox.attr('selected','selected'); - $stickychatCheckbox.change(); - $stickychatCheckbox.click(); + // select chat always on screen and fire change event + $stickychatCheckbox.click(); + + setTimeout(function() { + //check if chat changed to remove the stickychat Class + var hasStickyChatClass = $chatbox.hasClass("stickyChat"); + expect(hasStickyChatClass).to.be(false); + + done(); + }, 10) + }, 10) - //check if chat changed to remove the stickychat Class - var hasStickyChatClass = $chatbox.hasClass("stickyChat"); - expect(hasStickyChatClass).to.be(false); - done(); }); it("makes chat stick to right side of the screen then makes it one step smaller", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - - //click on the settings button to make settings visible - var $settingsButton = chrome$(".buttonicon-settings"); - $settingsButton.click(); + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; - //get the chat selector - var $stickychatCheckbox = chrome$("#options-stickychat"); + // open chat + chrome$('#chaticon').click(); - //select chat always on screen and fire change event - $stickychatCheckbox.attr('selected','selected'); - $stickychatCheckbox.change(); - $stickychatCheckbox.click(); + // select chat always on screen from chatbox + chrome$('.stick-to-screen-btn').click(); - //check if chat changed to get the stickychat Class - var $chatbox = chrome$("#chatbox"); - var hasStickyChatClass = $chatbox.hasClass("stickyChat"); - expect(hasStickyChatClass).to.be(true); + // due to animation, we need to make some timeout... + setTimeout(function() { + //check if chat changed to get the stickychat Class + var $chatbox = chrome$("#chatbox"); + var hasStickyChatClass = $chatbox.hasClass("stickyChat"); + expect(hasStickyChatClass).to.be(true); - //select chat always on screen and fire change event - chrome$('#titlecross').click(); + // select chat always on screen and fire change event + chrome$('#titlecross').click(); - //check if chat changed to remove the stickychat Class - var hasStickyChatClass = $chatbox.hasClass("stickyChat"); - expect(hasStickyChatClass).to.be(false); + setTimeout(function() { + //check if chat changed to remove the stickychat Class + var hasStickyChatClass = $chatbox.hasClass("stickyChat"); + expect(hasStickyChatClass).to.be(false); - done(); + done(); + }, 10) + }, 10) }); }); diff --git a/tests/frontend/specs/chat_load_messages.js b/tests/frontend/specs/chat_load_messages.js index 7b09b47e1b8..29040798d34 100644 --- a/tests/frontend/specs/chat_load_messages.js +++ b/tests/frontend/specs/chat_load_messages.js @@ -1,21 +1,21 @@ describe("chat-load-messages", function(){ var padName; - + it("creates a pad", function(done) { padName = helper.newPad(done); this.timeout(60000); }); it("adds a lot of messages", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; var chatButton = chrome$("#chaticon"); chatButton.click(); var chatInput = chrome$("#chatinput"); var chatText = chrome$("#chattext"); - + this.timeout(60000); - + var messages = 140; for(var i=1; i <= messages; i++) { var num = ''+i; @@ -33,7 +33,7 @@ describe("chat-load-messages", function(){ helper.newPad(done, padName); }); }); - + it("checks initial message count", function(done) { var chatText; var expectedCount = 101; @@ -48,7 +48,7 @@ describe("chat-load-messages", function(){ done(); }); }); - + it("loads more messages", function(done) { var expectedCount = 122; var chrome$ = helper.padChrome$; @@ -56,7 +56,7 @@ describe("chat-load-messages", function(){ chatButton.click(); var chatText = chrome$("#chattext"); var loadMsgBtn = chrome$("#chatloadmessagesbutton"); - + loadMsgBtn.click(); helper.waitFor(function(){ return chatText.children("p").length == expectedCount; @@ -65,7 +65,7 @@ describe("chat-load-messages", function(){ done(); }); }); - + it("checks for button vanishing", function(done) { var expectedDisplay = 'none'; var chrome$ = helper.padChrome$; diff --git a/tests/frontend/specs/clear_authorship_colors.js b/tests/frontend/specs/clear_authorship_colors.js index 1417f63c62f..efadb08a0f0 100644 --- a/tests/frontend/specs/clear_authorship_colors.js +++ b/tests/frontend/specs/clear_authorship_colors.js @@ -6,8 +6,8 @@ describe("clear authorship colors button", function(){ }); it("makes text clear authorship colors", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; // override the confirm dialogue functioon helper.padChrome$.window.confirm = function(){ @@ -19,7 +19,7 @@ describe("clear authorship colors button", function(){ // Get the original text var originalText = inner$("div").first().text(); - + // Set some new text var sentText = "Hello"; @@ -47,6 +47,76 @@ describe("clear authorship colors button", function(){ var hasAuthorClass = inner$("div").first().attr("class").indexOf("author") !== -1; expect(hasAuthorClass).to.be(false); + setTimeout(function(){ + var disconnectVisible = chrome$("div.disconnected").attr("class").indexOf("visible") === -1 + expect(disconnectVisible).to.be(true); + },1000); + + done(); + }); + + }); + + it("makes text clear authorship colors and checks it can't be undone", function(done) { + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; + + // override the confirm dialogue functioon + helper.padChrome$.window.confirm = function(){ + return true; + } + + //get the first text element out of the inner iframe + var $firstTextElement = inner$("div").first(); + + // Get the original text + var originalText = inner$("div").first().text(); + + // Set some new text + var sentText = "Hello"; + + //select this text element + $firstTextElement.sendkeys('{selectall}'); + $firstTextElement.sendkeys(sentText); + $firstTextElement.sendkeys('{rightarrow}'); + + helper.waitFor(function(){ + return inner$("div span").first().attr("class").indexOf("author") !== -1; // wait until we have the full value available + }).done(function(){ + //IE hates you if you don't give focus to the inner frame bevore you do a clearAuthorship + inner$("div").first().focus(); + + //get the clear authorship colors button and click it + var $clearauthorshipcolorsButton = chrome$(".buttonicon-clearauthorship"); + $clearauthorshipcolorsButton.click(); + + // does the first divs span include an author class? + console.log(inner$("div span").first().attr("class")); + var hasAuthorClass = inner$("div span").first().attr("class").indexOf("author") !== -1; + //expect(hasAuthorClass).to.be(false); + + // does the first div include an author class? + var hasAuthorClass = inner$("div").first().attr("class").indexOf("author") !== -1; + expect(hasAuthorClass).to.be(false); + + var e = inner$.Event(helper.evtType); + e.ctrlKey = true; // Control key + e.which = 90; // z + inner$("#innerdocbody").trigger(e); // shouldn't od anything + + // does the first div include an author class? + hasAuthorClass = inner$("div").first().attr("class").indexOf("author") !== -1; + expect(hasAuthorClass).to.be(false); + + // get undo and redo buttons + var $undoButton = chrome$(".buttonicon-undo"); + + // click the button + $undoButton.click(); // shouldn't do anything + hasAuthorClass = inner$("div").first().attr("class").indexOf("author") !== -1; + expect(hasAuthorClass).to.be(false); + + setTimeout(function(){ var disconnectVisible = chrome$("div.disconnected").attr("class").indexOf("visible") === -1 expect(disconnectVisible).to.be(true); @@ -57,3 +127,4 @@ describe("clear authorship colors button", function(){ }); }); + diff --git a/tests/frontend/specs/delete.js b/tests/frontend/specs/delete.js index 86e76f56f20..616cd4ddc51 100644 --- a/tests/frontend/specs/delete.js +++ b/tests/frontend/specs/delete.js @@ -6,12 +6,12 @@ describe("delete keystroke", function(){ }); it("makes text delete", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; + //get the first text element out of the inner iframe var $firstTextElement = inner$("div").first(); - + // get the original length of this element var elementLength = $firstTextElement.text().length; @@ -25,7 +25,7 @@ describe("delete keystroke", function(){ //ace creates a new dom element when you press a keystroke, so just get the first text element again var $newFirstTextElement = inner$("div").first(); - + // get the new length of this element var newElementLength = $newFirstTextElement.text().length; diff --git a/tests/frontend/specs/embed_value.js b/tests/frontend/specs/embed_value.js index 029f0dd5d91..aa031e2366e 100644 --- a/tests/frontend/specs/embed_value.js +++ b/tests/frontend/specs/embed_value.js @@ -16,9 +16,9 @@ describe("embed links", function(){ var $embediFrame = $(embedCode); //read and check the frame attributes - var width = $embediFrame.attr("width"); - var height = $embediFrame.attr("height"); - var name = $embediFrame.attr("name"); + var width = $embediFrame.attr("width"); + var height = $embediFrame.attr("height"); + var name = $embediFrame.attr("name"); expect(width).to.be('600'); expect(height).to.be('400'); expect(name).to.be(readonly ? "embed_readonly" : "embed_readwrite"); @@ -43,7 +43,7 @@ describe("embed links", function(){ } else { expect(url).to.be(helper.padChrome$.window.location.href); } - + //check if all parts of the url are like expected expect(params).to.eql(expectedParams); } @@ -57,7 +57,7 @@ describe("embed links", function(){ describe("the share link", function(){ it("is the actual pad url", function(done){ - var chrome$ = helper.padChrome$; + var chrome$ = helper.padChrome$; //open share dropdown chrome$(".buttonicon-embed").click(); @@ -73,14 +73,14 @@ describe("embed links", function(){ describe("the embed as iframe code", function(){ it("is an iframe with the the correct url parameters and correct size", function(done){ - var chrome$ = helper.padChrome$; + var chrome$ = helper.padChrome$; //open share dropdown chrome$(".buttonicon-embed").click(); //get the link of the share field + the actual pad url and compare them var embedCode = chrome$("#embedinput").val(); - + checkiFrameCode(embedCode, false) done(); @@ -96,7 +96,7 @@ describe("embed links", function(){ describe("the share link", function(){ it("shows a read only url", function(done){ - var chrome$ = helper.padChrome$; + var chrome$ = helper.padChrome$; //open share dropdown chrome$(".buttonicon-embed").click(); @@ -114,7 +114,7 @@ describe("embed links", function(){ describe("the embed as iframe code", function(){ it("is an iframe with the the correct url parameters and correct size", function(done){ - var chrome$ = helper.padChrome$; + var chrome$ = helper.padChrome$; //open share dropdown chrome$(".buttonicon-embed").click(); @@ -125,9 +125,9 @@ describe("embed links", function(){ //get the link of the share field + the actual pad url and compare them var embedCode = chrome$("#embedinput").val(); - + checkiFrameCode(embedCode, true); - + done(); }); }); diff --git a/tests/frontend/specs/enter.js b/tests/frontend/specs/enter.js index baafeded25b..9c3457b02f9 100644 --- a/tests/frontend/specs/enter.js +++ b/tests/frontend/specs/enter.js @@ -6,12 +6,12 @@ describe("enter keystroke", function(){ }); it("creates a new line & puts cursor onto a new line", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; + //get the first text element out of the inner iframe var $firstTextElement = inner$("div").first(); - + // get the original string value minus the last char var originalTextValue = $firstTextElement.text(); @@ -20,7 +20,7 @@ describe("enter keystroke", function(){ //ace creates a new dom element when you press a keystroke, so just get the first text element again var $newFirstTextElement = inner$("div").first(); - + helper.waitFor(function(){ return inner$("div").first().text() === ""; }).done(function(){ diff --git a/tests/frontend/specs/font_type.js b/tests/frontend/specs/font_type.js index d2c7bc636ba..9b149873e4d 100644 --- a/tests/frontend/specs/font_type.js +++ b/tests/frontend/specs/font_type.js @@ -6,8 +6,8 @@ describe("font select", function(){ }); it("makes text monospace", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; //click on the settings button to make settings visible var $settingsButton = chrome$(".buttonicon-settings"); diff --git a/tests/frontend/specs/helper.js b/tests/frontend/specs/helper.js index 727e47960e9..fa7ed4ddaec 100644 --- a/tests/frontend/specs/helper.js +++ b/tests/frontend/specs/helper.js @@ -20,7 +20,7 @@ describe("the test helper", function(){ }); it("gives me 3 jquery instances of chrome, outer and inner", function(done){ - this.timeout(5000); + this.timeout(10000); helper.newPad(function(){ //check if the jquery selectors have the desired elements @@ -136,7 +136,15 @@ describe("the test helper", function(){ helper.selectLines($startLine, $endLine, startOffset, endOffset); var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("ort lines to t"); + + /* + * replace() is required here because Firefox keeps the line breaks. + * + * I'm not sure this is ideal behavior of getSelection() where the text + * is not consistent between browsers but that's the situation so that's + * how I'm covering it in this test. + */ + expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm,""))).to.be("ort lines to t"); done(); }); @@ -154,7 +162,15 @@ describe("the test helper", function(){ helper.selectLines($startLine, $endLine, startOffset, endOffset); var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("ort lines to test"); + + /* + * replace() is required here because Firefox keeps the line breaks. + * + * I'm not sure this is ideal behavior of getSelection() where the text + * is not consistent between browsers but that's the situation so that's + * how I'm covering it in this test. + */ + expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm,""))).to.be("ort lines to test"); done(); }); @@ -172,7 +188,15 @@ describe("the test helper", function(){ helper.selectLines($startLine, $endLine, startOffset, endOffset); var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("ort lines "); + + /* + * replace() is required here because Firefox keeps the line breaks. + * + * I'm not sure this is ideal behavior of getSelection() where the text + * is not consistent between browsers but that's the situation so that's + * how I'm covering it in this test. + */ + expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm,""))).to.be("ort lines "); done(); }); @@ -190,7 +214,15 @@ describe("the test helper", function(){ helper.selectLines($startLine, $endLine, startOffset, endOffset); var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("ort lines to test"); + + /* + * replace() is required here because Firefox keeps the line breaks. + * + * I'm not sure this is ideal behavior of getSelection() where the text + * is not consistent between browsers but that's the situation so that's + * how I'm covering it in this test. + */ + expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm,""))).to.be("ort lines to test"); done(); }); @@ -205,7 +237,15 @@ describe("the test helper", function(){ helper.selectLines($startLine, $endLine); var selection = inner$.document.getSelection(); - expect(cleanText(selection.toString())).to.be("short lines to test"); + + /* + * replace() is required here because Firefox keeps the line breaks. + * + * I'm not sure this is ideal behavior of getSelection() where the text + * is not consistent between browsers but that's the situation so that's + * how I'm covering it in this test. + */ + expect(cleanText(selection.toString().replace(/(\r\n|\n|\r)/gm,""))).to.be("short lines to test"); done(); }); diff --git a/tests/frontend/specs/importexport.js b/tests/frontend/specs/importexport.js index 2dc002ba0cf..3466f7cfbc4 100644 --- a/tests/frontend/specs/importexport.js +++ b/tests/frontend/specs/importexport.js @@ -159,7 +159,7 @@ describe("import functionality", function(){ //
        • bullet4 line 2
        \n\ //
        \n') }) - + var results = exportfunc(helper.padChrome$.window.location.href) expect(results[0][1]).to.be('
        • bullet line 1
        • bullet line 2
          • bullet2 line 1
              • bullet4 line 2
              • bullet4 line 2
              • bullet4 line 2
            • bullet3 line 1
        • bullet2 line 1

        ') expect(results[1][1]).to.be('\t* bullet line 1\n\t* bullet line 2\n\t\t* bullet2 line 1\n\t\t\t\t* bullet4 line 2\n\t\t\t\t* bullet4 line 2\n\t\t\t\t* bullet4 line 2\n\t\t\t* bullet3 line 1\n\t* bullet2 line 1\n\n') @@ -183,11 +183,11 @@ describe("import functionality", function(){
        \n') }) var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
        • bullet line 1

        • bullet line 2
          • bullet2 line 1

              • bullet4 line 2 bisu
              • bullet4 line 2 bs
              • bullet4 line 2 uuis
                      • foo
                      • foobar bs
                • foobar

        ') + expect(results[0][1]).to.be('
        • bullet line 1

        • bullet line 2
          • bullet2 line 1

              • bullet4 line 2 bisu
              • bullet4 line 2 bs
              • bullet4 line 2 uuis
                      • foo
                      • foobar bs
                • foobar

        ') expect(results[1][1]).to.be('\t* bullet line 1\n\n\t* bullet line 2\n\t\t* bullet2 line 1\n\n\t\t\t\t* bullet4 line 2 bisu\n\t\t\t\t* bullet4 line 2 bs\n\t\t\t\t* bullet4 line 2 uuis\n\t\t\t\t\t\t\t\t* foo\n\t\t\t\t\t\t\t\t* foobar bs\n\t\t\t\t\t* foobar\n\n') done() }) - + xit("import a pad with ordered lists from html", function(done){ var importurl = helper.padChrome$.window.location.href+'/import' var htmlWithBullets = '
        1. number 1 line 1
        1. number 2 line 2
        ' diff --git a/tests/frontend/specs/importindents.js b/tests/frontend/specs/importindents.js index 326d9e971a6..284a90f3281 100644 --- a/tests/frontend/specs/importindents.js +++ b/tests/frontend/specs/importindents.js @@ -66,7 +66,7 @@ describe("import indents functionality", function(){ expect(results[1][1]).to.be('\tindent line 1\n\tindent line 2\n\t\tindent2 line 1\n\t\tindent2 line 2\n\n') done() }) - + xit("import a pad with indented lists and newlines from html", function(done){ var importurl = helper.padChrome$.window.location.href+'/import' var htmlWithIndents = '
        • indent line 1

        • indent 1 line 2
          • indent 2 times line 1

          • indent 2 times line 2
        ' @@ -104,7 +104,7 @@ describe("import indents functionality", function(){
        \n') }) var results = exportfunc(helper.padChrome$.window.location.href) - expect(results[0][1]).to.be('
        • indent line 1

        • indent line 2
          • indent2 line 1

              • indent4 line 2 bisu
              • indent4 line 2 bs
              • indent4 line 2 uuis
                      • foo
                      • foobar bs
                • foobar

        ') + expect(results[0][1]).to.be('
        • indent line 1

        • indent line 2
          • indent2 line 1

              • indent4 line 2 bisu
              • indent4 line 2 bs
              • indent4 line 2 uuis
                      • foo
                      • foobar bs
                • foobar

        ') expect(results[1][1]).to.be('\tindent line 1\n\n\tindent line 2\n\t\tindent2 line 1\n\n\t\t\t\tindent4 line 2 bisu\n\t\t\t\tindent4 line 2 bs\n\t\t\t\tindent4 line 2 uuis\n\t\t\t\t\t\t\t\tfoo\n\t\t\t\t\t\t\t\tfoobar bs\n\t\t\t\t\tfoobar\n\n') done() }) diff --git a/tests/frontend/specs/indentation.js b/tests/frontend/specs/indentation.js index dd12fc317c4..2173f9e07ff 100644 --- a/tests/frontend/specs/indentation.js +++ b/tests/frontend/specs/indentation.js @@ -15,13 +15,7 @@ describe("indentation button", function(){ //select this text element $firstTextElement.sendkeys('{selectall}'); - if(inner$(window)[0].bowser.modernIE){ // if it's IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - - var e = inner$.Event(evtType); + var e = inner$.Event(helper.evtType); e.keyCode = 9; // tab :| inner$("#innerdocbody").trigger(e); @@ -325,12 +319,7 @@ describe("indentation button", function(){ function pressEnter(){ var inner$ = helper.padInner$; - if(inner$(window)[0].bowser.modernIE){ // if it's IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - var e = inner$.Event(evtType); + var e = inner$.Event(helper.evtType); e.keyCode = 13; // enter :| inner$("#innerdocbody").trigger(e); } diff --git a/tests/frontend/specs/italic.js b/tests/frontend/specs/italic.js index cecbc180831..3c62e00e86b 100644 --- a/tests/frontend/specs/italic.js +++ b/tests/frontend/specs/italic.js @@ -6,22 +6,22 @@ describe("italic some text", function(){ }); it("makes text italic using button", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; //get the first text element out of the inner iframe var $firstTextElement = inner$("div").first(); - + //select this text element $firstTextElement.sendkeys('{selectall}'); //get the bold button and click it var $boldButton = chrome$(".buttonicon-italic"); $boldButton.click(); - + //ace creates a new dom element when you press a button, so just get the first text element again var $newFirstTextElement = inner$("div").first(); - + // is there a element now? var isItalic = $newFirstTextElement.find("i").length === 1; @@ -44,13 +44,7 @@ describe("italic some text", function(){ //select this text element $firstTextElement.sendkeys('{selectall}'); - if(inner$(window)[0].bowser.modernIE){ // if it's IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - - var e = inner$.Event(evtType); + var e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = 105; // i inner$("#innerdocbody").trigger(e); diff --git a/tests/frontend/specs/ordered_list.js b/tests/frontend/specs/ordered_list.js index e7509e883e8..f4aa572731c 100644 --- a/tests/frontend/specs/ordered_list.js +++ b/tests/frontend/specs/ordered_list.js @@ -111,12 +111,7 @@ describe("assign ordered list", function(){ var triggerCtrlShiftShortcut = function(shortcutChar) { var inner$ = helper.padInner$; - if(inner$(window)[0].bowser.modernIE) { // if it's IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - var e = inner$.Event(evtType); + var e = inner$.Event(helper.evtType); e.ctrlKey = true; e.shiftKey = true; e.which = shortcutChar.toString().charCodeAt(0); diff --git a/tests/frontend/specs/pad_modal.js b/tests/frontend/specs/pad_modal.js index 80752e4b829..15a8bc138b2 100644 --- a/tests/frontend/specs/pad_modal.js +++ b/tests/frontend/specs/pad_modal.js @@ -1,6 +1,6 @@ describe('Pad modal', function() { context('when modal is a "force reconnect" message', function() { - var MODAL_SELECTOR = '#connectivity .slowcommit'; + var MODAL_SELECTOR = '#connectivity'; beforeEach(function(done) { helper.newPad(function() { @@ -10,7 +10,7 @@ describe('Pad modal', function() { // wait for modal to be displayed var $modal = helper.padChrome$(MODAL_SELECTOR); helper.waitFor(function() { - return $modal.is(':visible'); + return $modal.hasClass('popup-show'); }, 50000).done(done); }); @@ -30,7 +30,7 @@ describe('Pad modal', function() { it('does not close the modal', function(done) { var $modal = helper.padChrome$(MODAL_SELECTOR); - var modalIsVisible = $modal.is(':visible'); + var modalIsVisible = $modal.hasClass('popup-show'); expect(modalIsVisible).to.be(true); @@ -45,7 +45,7 @@ describe('Pad modal', function() { it('does not close the modal', function(done) { var $modal = helper.padChrome$(MODAL_SELECTOR); - var modalIsVisible = $modal.is(':visible'); + var modalIsVisible = $modal.hasClass('popup-show'); expect(modalIsVisible).to.be(true); @@ -126,6 +126,7 @@ describe('Pad modal', function() { var isModalOpened = function(modalSelector) { var $modal = helper.padChrome$(modalSelector); - return $modal.is(':visible'); + + return $modal.hasClass('popup-show'); } }); diff --git a/tests/frontend/specs/redo.js b/tests/frontend/specs/redo.js index caa32feec7d..a8e874da76b 100644 --- a/tests/frontend/specs/redo.js +++ b/tests/frontend/specs/redo.js @@ -7,7 +7,7 @@ describe("undo button then redo button", function(){ it("redo some typing with button", function(done){ var inner$ = helper.padInner$; var chrome$ = helper.padChrome$; - + // get the first text element inside the editable space var $firstTextElement = inner$("div span").first(); var originalValue = $firstTextElement.text(); // get the original value @@ -47,18 +47,12 @@ describe("undo button then redo button", function(){ var modifiedValue = $firstTextElement.text(); // get the modified value expect(modifiedValue).not.to.be(originalValue); // expect the value to change - if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - - var e = inner$.Event(evtType); + var e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = 90; // z inner$("#innerdocbody").trigger(e); - var e = inner$.Event(evtType); + var e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = 121; // y inner$("#innerdocbody").trigger(e); diff --git a/tests/frontend/specs/scroll.js b/tests/frontend/specs/scroll.js deleted file mode 100644 index 94756b85666..00000000000 --- a/tests/frontend/specs/scroll.js +++ /dev/null @@ -1,649 +0,0 @@ -describe('scroll when focus line is out of viewport', function () { - before(function (done) { - helper.newPad(function(){ - cleanPad(function(){ - forceUseMonospacedFont(); - scrollWhenPlaceCaretInTheLastLineOfViewport(); - createPadWithSeveralLines(function(){ - resizeEditorHeight(); - done(); - }); - }); - }); - this.timeout(20000); - }); - - context('when user presses any arrow keys on a line above the viewport', function(){ - context('and scroll percentage config is set to 0.2 on settings.json', function(){ - var lineCloseOfTopOfPad = 10; - before(function (done) { - setScrollPercentageWhenFocusLineIsOutOfViewport(0.2, true); - scrollEditorToBottomOfPad(); - - placeCaretInTheBeginningOfLine(lineCloseOfTopOfPad, function(){ // place caret in the 10th line - // warning: even pressing right arrow, the caret does not change of position - // the column where the caret is, it has not importance, only the line - pressAndReleaseRightArrow(); - done(); - }); - }); - - it('keeps the focus line scrolled 20% from the top of the viewport', function (done) { - // default behavior is to put the line in the top of viewport, but as - // scrollPercentageWhenFocusLineIsOutOfViewport is set to 0.2, we have an extra 20% of lines scrolled - // (2 lines, which are the 20% of the 10 that are visible on viewport) - var firstLineOfViewport = getFirstLineVisibileOfViewport(); - expect(lineCloseOfTopOfPad).to.be(firstLineOfViewport + 2); - done(); - }); - }); - }); - - context('when user presses any arrow keys on a line below the viewport', function(){ - context('and scroll percentage config is set to 0.7 on settings.json', function(){ - var lineCloseToBottomOfPad = 50; - before(function (done) { - setScrollPercentageWhenFocusLineIsOutOfViewport(0.7); - - // firstly, scroll to make the lineCloseToBottomOfPad visible. After that, scroll to make it out of viewport - scrollEditorToTopOfPad(); - placeCaretAtTheEndOfLine(lineCloseToBottomOfPad); // place caret in the 50th line - setTimeout(function() { - // warning: even pressing right arrow, the caret does not change of position - pressAndReleaseLeftArrow(); - done(); - }, 1000); - }); - - it('keeps the focus line scrolled 70% from the bottom of the viewport', function (done) { - // default behavior is to put the line in the top of viewport, but as - // scrollPercentageWhenFocusLineIsOutOfViewport is set to 0.7, we have an extra 70% of lines scrolled - // (7 lines, which are the 70% of the 10 that are visible on viewport) - var lastLineOfViewport = getLastLineVisibleOfViewport(); - expect(lineCloseToBottomOfPad).to.be(lastLineOfViewport - 7); - done(); - }); - }); - }); - - context('when user presses arrow up on the first line of the viewport', function(){ - context('and percentageToScrollWhenUserPressesArrowUp is set to 0.3', function () { - var lineOnTopOfViewportWhenThePadIsScrolledDown; - before(function (done) { - setPercentageToScrollWhenUserPressesArrowUp(0.3); - - // we need some room to make the scroll up - scrollEditorToBottomOfPad(); - lineOnTopOfViewportWhenThePadIsScrolledDown = 91; - placeCaretAtTheEndOfLine(lineOnTopOfViewportWhenThePadIsScrolledDown); - setTimeout(function() { - // warning: even pressing up arrow, the caret does not change of position - pressAndReleaseUpArrow(); - done(); - }, 1000); - }); - - it('keeps the focus line scrolled 30% of the top of the viewport', function (done) { - // default behavior is to put the line in the top of viewport, but as - // PercentageToScrollWhenUserPressesArrowUp is set to 0.3, we have an extra 30% of lines scrolled - // (3 lines, which are the 30% of the 10 that are visible on viewport) - var firstLineOfViewport = getFirstLineVisibileOfViewport(); - expect(firstLineOfViewport).to.be(lineOnTopOfViewportWhenThePadIsScrolledDown - 3); - done(); - }) - }); - }); - - context('when user edits the last line of viewport', function(){ - context('and scroll percentage config is set to 0 on settings.json', function(){ - var lastLineOfViewportBeforeEnter = 10; - before(function () { - // the default value - resetScrollPercentageWhenFocusLineIsOutOfViewport(); - - // make sure the last line on viewport is the 10th one - scrollEditorToTopOfPad(); - placeCaretAtTheEndOfLine(lastLineOfViewportBeforeEnter); - pressEnter(); - }); - - it('keeps the focus line on the bottom of the viewport', function (done) { - var lastLineOfViewportAfterEnter = getLastLineVisibleOfViewport(); - expect(lastLineOfViewportAfterEnter).to.be(lastLineOfViewportBeforeEnter + 1); - done(); - }); - }); - - context('and scrollPercentageWhenFocusLineIsOutOfViewport is set to 0.3', function(){ // this value is arbitrary - var lastLineOfViewportBeforeEnter = 9; - before(function () { - setScrollPercentageWhenFocusLineIsOutOfViewport(0.3); - - // make sure the last line on viewport is the 10th one - scrollEditorToTopOfPad(); - placeCaretAtTheEndOfLine(lastLineOfViewportBeforeEnter); - pressBackspace(); - }); - - it('scrolls 30% of viewport up', function (done) { - var lastLineOfViewportAfterEnter = getLastLineVisibleOfViewport(); - // default behavior is to scroll one line at the bottom of viewport, but as - // scrollPercentageWhenFocusLineIsOutOfViewport is set to 0.3, we have an extra 30% of lines scrolled - // (3 lines, which are the 30% of the 10 that are visible on viewport) - expect(lastLineOfViewportAfterEnter).to.be(lastLineOfViewportBeforeEnter + 3); - done(); - }); - }); - - context('and it is set to a value that overflow the interval [0, 1]', function(){ - var lastLineOfViewportBeforeEnter = 10; - before(function(){ - var scrollPercentageWhenFocusLineIsOutOfViewport = 1.5; - scrollEditorToTopOfPad(); - placeCaretAtTheEndOfLine(lastLineOfViewportBeforeEnter); - setScrollPercentageWhenFocusLineIsOutOfViewport(scrollPercentageWhenFocusLineIsOutOfViewport); - pressEnter(); - }); - - it('keeps the default behavior of moving the focus line on the bottom of the viewport', function (done) { - var lastLineOfViewportAfterEnter = getLastLineVisibleOfViewport(); - expect(lastLineOfViewportAfterEnter).to.be(lastLineOfViewportBeforeEnter + 1); - done(); - }); - }); - }); - - context('when user edits a line above the viewport', function(){ - context('and scroll percentage config is set to 0 on settings.json', function(){ - var lineCloseOfTopOfPad = 10; - before(function () { - // the default value - setScrollPercentageWhenFocusLineIsOutOfViewport(0); - - // firstly, scroll to make the lineCloseOfTopOfPad visible. After that, scroll to make it out of viewport - scrollEditorToTopOfPad(); - placeCaretAtTheEndOfLine(lineCloseOfTopOfPad); // place caret in the 10th line - scrollEditorToBottomOfPad(); - pressBackspace(); // edit the line where the caret is, which is above the viewport - }); - - it('keeps the focus line on the top of the viewport', function (done) { - var firstLineOfViewportAfterEnter = getFirstLineVisibileOfViewport(); - expect(firstLineOfViewportAfterEnter).to.be(lineCloseOfTopOfPad); - done(); - }); - }); - - context('and scrollPercentageWhenFocusLineIsOutOfViewport is set to 0.2', function(){ // this value is arbitrary - var lineCloseToBottomOfPad = 50; - before(function () { - // we force the line edited to be above the top of the viewport - setScrollPercentageWhenFocusLineIsOutOfViewport(0.2, true); // set scroll jump to 20% - scrollEditorToTopOfPad(); - placeCaretAtTheEndOfLine(lineCloseToBottomOfPad); - scrollEditorToBottomOfPad(); - pressBackspace(); // edit line - }); - - it('scrolls 20% of viewport down', function (done) { - // default behavior is to scroll one line at the top of viewport, but as - // scrollPercentageWhenFocusLineIsOutOfViewport is set to 0.2, we have an extra 20% of lines scrolled - // (2 lines, which are the 20% of the 10 that are visible on viewport) - var firstLineVisibileOfViewport = getFirstLineVisibileOfViewport(); - expect(lineCloseToBottomOfPad).to.be(firstLineVisibileOfViewport + 2); - done(); - }); - }); - }); - - context('when user places the caret at the last line visible of viewport', function(){ - var lastLineVisible; - context('and scroll percentage config is set to 0 on settings.json', function(){ - before(function (done) { - // reset to the default value - resetScrollPercentageWhenFocusLineIsOutOfViewport(); - - placeCaretInTheBeginningOfLine(0, function(){ // reset caret position - scrollEditorToTopOfPad(); - lastLineVisible = getLastLineVisibleOfViewport(); - placeCaretInTheBeginningOfLine(lastLineVisible, done); // place caret in the 9th line - }); - - }); - - it('does not scroll', function(done){ - setTimeout(function() { - var lastLineOfViewport = getLastLineVisibleOfViewport(); - var lineDoesNotScroll = lastLineOfViewport === lastLineVisible; - expect(lineDoesNotScroll).to.be(true); - done(); - }, 1000); - }); - }); - context('and scroll percentage config is set to 0.5 on settings.json', function(){ - before(function (done) { - setScrollPercentageWhenFocusLineIsOutOfViewport(0.5); - scrollEditorToTopOfPad(); - placeCaretInTheBeginningOfLine(0, function(){ // reset caret position - // this timeout inside a callback is ugly but it necessary to give time to aceSelectionChange - // realizes that the selection has been changed - setTimeout(function() { - lastLineVisible = getLastLineVisibleOfViewport(); - placeCaretInTheBeginningOfLine(lastLineVisible, done); // place caret in the 9th line - }, 1000); - }); - }); - - it('scrolls line to 50% of the viewport', function(done){ - helper.waitFor(function(){ - var lastLineOfViewport = getLastLineVisibleOfViewport(); - var lastLinesScrolledFiveLinesUp = lastLineOfViewport - 5 === lastLineVisible; - return lastLinesScrolledFiveLinesUp; - }).done(done); - }); - }); - }); - - // This is a special case. When user is selecting a text with arrow down or arrow left we have - // to keep the last line selected on focus - context('when the first line selected is out of the viewport and user presses shift arrow down', function(){ - var lastLineOfPad = 99; - before(function (done) { - scrollEditorToTopOfPad(); - - // make a selection bigger than the viewport height - var $firstLineOfSelection = getLine(0); - var $lastLineOfSelection = getLine(lastLineOfPad); - var lengthOfLastLine = $lastLineOfSelection.text().length; - helper.selectLines($firstLineOfSelection, $lastLineOfSelection, 0, lengthOfLastLine); - - // place the last line selected on the viewport - scrollEditorToBottomOfPad(); - - // press a key to make the selection goes down - // although we can't simulate the extending of selection. It's possible to send a key event - // which is captured on ace2_inner scroll function. - pressAndReleaseLeftArrow(true); - done(); - }); - - it('keeps the last line selected on focus', function (done) { - var lastLineOfSelectionIsVisible = isLineOnViewport(lastLineOfPad); - expect(lastLineOfSelectionIsVisible).to.be(true); - done(); - }); - }); - - // In this scenario we avoid the bouncing scroll. E.g Let's suppose we have a big line that is - // the size of the viewport, and its top is above the viewport. When user presses '<-', this line - // will scroll down because the top is out of the viewport. When it scrolls down, the bottom of - // line gets below the viewport so when user presses '<-' again it scrolls up to make the bottom - // of line visible. If user presses arrow keys more than one time, the editor will keep scrolling up and down - context('when the line height is bigger than the scroll amount percentage * viewport height', function(){ - var scrollOfEditorBeforePressKey; - var BIG_LINE_NUMBER = 0; - var MIDDLE_OF_BIG_LINE = 51; - before(function (done) { - createPadWithALineHigherThanViewportHeight(this, BIG_LINE_NUMBER, function(){ - setScrollPercentageWhenFocusLineIsOutOfViewport(0.5); // set any value to force scroll to outside to viewport - var $bigLine = getLine(BIG_LINE_NUMBER); - - // each line has about 5 chars, we place the caret in the middle of the line - helper.selectLines($bigLine, $bigLine, MIDDLE_OF_BIG_LINE, MIDDLE_OF_BIG_LINE); - - scrollEditorToLeaveTopAndBottomOfBigLineOutOfViewport($bigLine); - scrollOfEditorBeforePressKey = getEditorScroll(); - - // press a key to force to scroll - pressAndReleaseRightArrow(); - done(); - }); - }); - - // reset pad to the original text - after(function (done) { - this.timeout(5000); - cleanPad(function(){ - createPadWithSeveralLines(function(){ - resetEditorWidth(); - done(); - }); - }); - }); - - // as the editor.line is inside of the viewport, it should not scroll - it('should not scroll', function (done) { - var scrollOfEditorAfterPressKey = getEditorScroll(); - expect(scrollOfEditorAfterPressKey).to.be(scrollOfEditorBeforePressKey); - done(); - }); - }); - - // Some plugins, for example the ep_page_view, change the editor dimensions. This plugin, for example, - // adds padding-top to the ace_outer, which changes the viewport height - describe('integration with plugins which changes the margin of editor', function(){ - context('when editor dimensions changes', function(){ - before(function () { - // reset the size of editor. Now we show more than 10 lines as in the other tests - resetResizeOfEditorHeight(); - scrollEditorToTopOfPad(); - - // height of the editor viewport - var editorHeight = getEditorHeight(); - - // add a big padding-top, 50% of the viewport - var paddingTopOfAceOuter = editorHeight/2; - var chrome$ = helper.padChrome$; - var $outerIframe = chrome$('iframe'); - $outerIframe.css('padding-top', paddingTopOfAceOuter); - - // we set a big value to check if the scroll is made - setScrollPercentageWhenFocusLineIsOutOfViewport(1); - }); - - context('and user places the caret in the last line visible of the pad', function(){ - var lastLineVisible; - beforeEach(function (done) { - lastLineVisible = getLastLineVisibleOfViewport(); - placeCaretInTheBeginningOfLine(lastLineVisible, done); - }); - - it('scrolls the line where caret is', function(done){ - helper.waitFor(function(){ - var firstLineVisibileOfViewport = getFirstLineVisibileOfViewport(); - var linesScrolled = firstLineVisibileOfViewport !== 0; - return linesScrolled; - }).done(done); - }); - }); - }); - }); - - /* ********************* Helper functions/constants ********************* */ - var TOP_OF_PAGE = 0; - var BOTTOM_OF_PAGE = 5000; // we use a big value to force the page to be scrolled all the way down - var LINES_OF_PAD = 100; - var ENTER = 13; - var BACKSPACE = 8; - var LEFT_ARROW = 37; - var UP_ARROW = 38; - var RIGHT_ARROW = 39; - var LINES_ON_VIEWPORT = 10; - var WIDTH_OF_EDITOR_RESIZED = 100; - var LONG_TEXT_CHARS = 100; - - var cleanPad = function(callback) { - var inner$ = helper.padInner$; - var $padContent = inner$('#innerdocbody'); - $padContent.html(''); - - // wait for Etherpad to re-create first line - helper.waitFor(function(){ - var lineNumber = inner$('div').length; - return lineNumber === 1; - }, 2000).done(callback); - }; - - var createPadWithSeveralLines = function(done) { - var line = 'a
        '; - var $firstLine = helper.padInner$('div').first(); - var lines = line.repeat(LINES_OF_PAD); //arbitrary number, we need to create lines that is over the viewport - $firstLine.html(lines); - - helper.waitFor(function(){ - var linesCreated = helper.padInner$('div').length; - return linesCreated === LINES_OF_PAD; - }, 4000).done(done); - }; - - var createPadWithALineHigherThanViewportHeight = function(test, line, done) { - var viewportHeight = 160; //10 lines * 16px (height of line) - test.timeout(5000); - cleanPad(function(){ - // make the editor smaller to make test easier - // with that width the each line has about 5 chars - resizeEditorWidth(); - - // we create a line with 100 chars, which makes about 20 lines - setLongTextOnLine(line); - helper.waitFor(function () { - var $firstLine = getLine(line); - - var heightOfLine = $firstLine.get(0).getBoundingClientRect().height; - return heightOfLine >= viewportHeight; - }, 4000).done(done); - }); - }; - - var setLongTextOnLine = function(line) { - var $line = getLine(line); - var longText = 'a'.repeat(LONG_TEXT_CHARS); - $line.html(longText); - }; - - // resize the editor to make the tests easier - var resizeEditorHeight = function() { - var chrome$ = helper.padChrome$; - chrome$('#editorcontainer').css('height', getSizeOfViewport()); - }; - - // this makes about 5 chars per line - var resizeEditorWidth = function() { - var chrome$ = helper.padChrome$; - chrome$('#editorcontainer').css('width', WIDTH_OF_EDITOR_RESIZED); - }; - - var resetResizeOfEditorHeight = function() { - var chrome$ = helper.padChrome$; - chrome$('#editorcontainer').css('height', ''); - }; - - var resetEditorWidth = function () { - var chrome$ = helper.padChrome$; - chrome$('#editorcontainer').css('width', ''); - }; - - var getEditorHeight = function() { - var chrome$ = helper.padChrome$; - var $editor = chrome$('#editorcontainer'); - var editorHeight = $editor.get(0).clientHeight; - return editorHeight; - }; - - var getSizeOfViewport = function() { - return getLinePositionOnViewport(LINES_ON_VIEWPORT) - getLinePositionOnViewport(0); - }; - - var scrollPageTo = function(value) { - var outer$ = helper.padOuter$; - var $ace_outer = outer$('#outerdocbody').parent(); - $ace_outer.parent().scrollTop(value); - }; - - var scrollEditorToTopOfPad = function() { - scrollPageTo(TOP_OF_PAGE); - }; - - var scrollEditorToBottomOfPad = function() { - scrollPageTo(BOTTOM_OF_PAGE); - }; - - var scrollEditorToLeaveTopAndBottomOfBigLineOutOfViewport = function ($bigLine) { - var lineHeight = $bigLine.get(0).getBoundingClientRect().height; - var middleOfLine = lineHeight/2; - scrollPageTo(middleOfLine); - }; - - var getLine = function(lineNum) { - var inner$ = helper.padInner$; - var $line = inner$('div').eq(lineNum); - return $line; - }; - - var placeCaretAtTheEndOfLine = function(lineNum) { - var $targetLine = getLine(lineNum); - var lineLength = $targetLine.text().length; - helper.selectLines($targetLine, $targetLine, lineLength, lineLength); - }; - - var placeCaretInTheBeginningOfLine = function(lineNum, cb) { - var $targetLine = getLine(lineNum); - helper.selectLines($targetLine, $targetLine, 0, 0); - helper.waitFor(function() { - var $lineWhereCaretIs = getLineWhereCaretIs(); - return $targetLine.get(0) === $lineWhereCaretIs.get(0); - }).done(cb); - }; - - var getLineWhereCaretIs = function() { - var inner$ = helper.padInner$; - var nodeWhereCaretIs = inner$.document.getSelection().anchorNode; - var $lineWhereCaretIs = $(nodeWhereCaretIs).closest('div'); - return $lineWhereCaretIs; - }; - - var getFirstLineVisibileOfViewport = function() { - return _.find(_.range(0, LINES_OF_PAD - 1), isLineOnViewport); - }; - - var getLastLineVisibleOfViewport = function() { - return _.find(_.range(LINES_OF_PAD - 1, 0, -1), isLineOnViewport); - }; - - var pressKey = function(keyCode, shiftIsPressed){ - var inner$ = helper.padInner$; - var evtType; - if(inner$(window)[0].bowser.modernIE){ // if it's IE - evtType = 'keypress'; - }else{ - evtType = 'keydown'; - } - var e = inner$.Event(evtType); - e.shiftKey = shiftIsPressed; - e.keyCode = keyCode; - e.which = keyCode; // etherpad listens to 'which' - inner$('#innerdocbody').trigger(e); - }; - - var releaseKey = function(keyCode){ - var inner$ = helper.padInner$; - var evtType = 'keyup'; - var e = inner$.Event(evtType); - e.keyCode = keyCode; - e.which = keyCode; // etherpad listens to 'which' - inner$('#innerdocbody').trigger(e); - }; - - var pressEnter = function() { - pressKey(ENTER); - }; - - var pressBackspace = function() { - pressKey(BACKSPACE); - }; - - var pressAndReleaseUpArrow = function() { - pressKey(UP_ARROW); - releaseKey(UP_ARROW); - }; - - var pressAndReleaseRightArrow = function() { - pressKey(RIGHT_ARROW); - releaseKey(RIGHT_ARROW); - }; - - var pressAndReleaseLeftArrow = function(shiftIsPressed) { - pressKey(LEFT_ARROW, shiftIsPressed); - releaseKey(LEFT_ARROW); - }; - - var isLineOnViewport = function(lineNumber) { - // in the function scrollNodeVerticallyIntoView from ace2_inner.js, iframePadTop is used to calculate - // how much scroll is needed. Although the name refers to padding-top, this value is not set on the - // padding-top. - var iframePadTop = 8; - var $line = getLine(lineNumber); - var linePosition = $line.get(0).getBoundingClientRect(); - - // position relative to the current viewport - var linePositionTopOnViewport = linePosition.top - getEditorScroll() + iframePadTop; - var linePositionBottomOnViewport = linePosition.bottom - getEditorScroll(); - - var lineBellowTop = linePositionBottomOnViewport > 0; - var lineAboveBottom = linePositionTopOnViewport < getClientHeightVisible(); - var isVisible = lineBellowTop && lineAboveBottom; - - return isVisible; - }; - - var getEditorScroll = function () { - var outer$ = helper.padOuter$; - var scrollTopFirefox = outer$('#outerdocbody').parent().scrollTop(); // works only on firefox - var scrollTop = outer$('#outerdocbody').scrollTop() || scrollTopFirefox; - return scrollTop; - }; - - // clientHeight includes padding, so we have to subtract it and consider only the visible viewport - var getClientHeightVisible = function () { - var outer$ = helper.padOuter$; - var $ace_outer = outer$('#outerdocbody').parent(); - var ace_outerHeight = $ace_outer.get(0).clientHeight; - var ace_outerPaddingTop = getIntValueOfCSSProperty($ace_outer, 'padding-top'); - var paddingAddedWhenPageViewIsEnable = getPaddingAddedWhenPageViewIsEnable(); - var clientHeight = ace_outerHeight - ( ace_outerPaddingTop + paddingAddedWhenPageViewIsEnable); - - return clientHeight; - }; - - // ep_page_view changes the dimensions of the editor. We have to guarantee - // the viewport height is calculated right - var getPaddingAddedWhenPageViewIsEnable = function () { - var chrome$ = helper.padChrome$; - var $outerIframe = chrome$('iframe'); - var paddingAddedWhenPageViewIsEnable = parseInt($outerIframe.css('padding-top')); - return paddingAddedWhenPageViewIsEnable; - }; - - var getIntValueOfCSSProperty = function($element, property){ - var valueString = $element.css(property); - return parseInt(valueString) || 0; - }; - - var forceUseMonospacedFont = function () { - helper.padChrome$.window.clientVars.padOptions.useMonospaceFont = true; - }; - - var setScrollPercentageWhenFocusLineIsOutOfViewport = function(value, editionAboveViewport) { - var scrollSettings = helper.padChrome$.window.clientVars.scrollWhenFocusLineIsOutOfViewport; - if (editionAboveViewport) { - scrollSettings.percentage.editionAboveViewport = value; - }else{ - scrollSettings.percentage.editionBelowViewport = value; - } - }; - - var resetScrollPercentageWhenFocusLineIsOutOfViewport = function() { - var scrollSettings = helper.padChrome$.window.clientVars.scrollWhenFocusLineIsOutOfViewport; - scrollSettings.percentage.editionAboveViewport = 0; - scrollSettings.percentage.editionBelowViewport = 0; - }; - - var setPercentageToScrollWhenUserPressesArrowUp = function (value) { - var scrollSettings = helper.padChrome$.window.clientVars.scrollWhenFocusLineIsOutOfViewport; - scrollSettings.percentageToScrollWhenUserPressesArrowUp = value; - }; - - var scrollWhenPlaceCaretInTheLastLineOfViewport = function() { - var scrollSettings = helper.padChrome$.window.clientVars.scrollWhenFocusLineIsOutOfViewport; - scrollSettings.scrollWhenCaretIsInTheLastLineOfViewport = true; - }; - - var getLinePositionOnViewport = function(lineNumber) { - var $line = getLine(lineNumber); - var linePosition = $line.get(0).getBoundingClientRect(); - - // position relative to the current viewport - return linePosition.top - getEditorScroll(); - }; -}); - diff --git a/tests/frontend/specs/select_formatting_buttons.js b/tests/frontend/specs/select_formatting_buttons.js index b6ec6d0c3e9..57285895783 100644 --- a/tests/frontend/specs/select_formatting_buttons.js +++ b/tests/frontend/specs/select_formatting_buttons.js @@ -88,13 +88,7 @@ describe("select formatting buttons when selection has style applied", function( //select this text element $firstTextElement.sendkeys('{selectall}'); - if(inner$(window)[0].bowser.modernIE){ // if it's IE - var evtType = "keypress"; - }else{ - var evtType = "keydown"; - } - - var e = inner$.Event(evtType); + var e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = key.charCodeAt(0); // I, U, B, 5 inner$("#innerdocbody").trigger(e); diff --git a/tests/frontend/specs/strikethrough.js b/tests/frontend/specs/strikethrough.js index 9afcea0fd5e..dc37b36f451 100644 --- a/tests/frontend/specs/strikethrough.js +++ b/tests/frontend/specs/strikethrough.js @@ -6,22 +6,22 @@ describe("strikethrough button", function(){ }); it("makes text strikethrough", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; //get the first text element out of the inner iframe var $firstTextElement = inner$("div").first(); - + //select this text element $firstTextElement.sendkeys('{selectall}'); //get the strikethrough button and click it var $strikethroughButton = chrome$(".buttonicon-strikethrough"); $strikethroughButton.click(); - + //ace creates a new dom element when you press a button, so just get the first text element again var $newFirstTextElement = inner$("div").first(); - + // is there a element now? var isstrikethrough = $newFirstTextElement.find("s").length === 1; diff --git a/tests/frontend/specs/timeslider.js b/tests/frontend/specs/timeslider.js index cb37bacb6ea..bca80ba495c 100644 --- a/tests/frontend/specs/timeslider.js +++ b/tests/frontend/specs/timeslider.js @@ -8,7 +8,7 @@ xdescribe("timeslider button takes you to the timeslider of a pad", function(){ it("timeslider contained in URL", function(done){ var inner$ = helper.padInner$; var chrome$ = helper.padChrome$; - + // get the first text element inside the editable space var $firstTextElement = inner$("div span").first(); var originalValue = $firstTextElement.text(); // get the original value diff --git a/tests/frontend/specs/timeslider_labels.js b/tests/frontend/specs/timeslider_labels.js index d39685efe43..09213a45227 100644 --- a/tests/frontend/specs/timeslider_labels.js +++ b/tests/frontend/specs/timeslider_labels.js @@ -6,9 +6,9 @@ describe("timeslider", function(){ }); it("Shows a date and time in the timeslider and make sure it doesn't include NaN", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; + // make some changes to produce 100 revisions var revs = 10; this.timeout(60000); @@ -18,15 +18,15 @@ describe("timeslider", function(){ inner$("div").first().sendkeys('a'); }, 200); } - + setTimeout(function() { // go to timeslider $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider'); - + setTimeout(function() { var timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; var $sliderBar = timeslider$('#ui-slider-bar'); - + var latestContents = timeslider$('#padcontent').text(); // Expect the date and time to be shown @@ -36,17 +36,17 @@ describe("timeslider", function(){ e.clientX = e.pageX = 150; e.clientY = e.pageY = 45; $sliderBar.trigger(e); - + e = new jQuery.Event('mousedown'); e.clientX = e.pageX = 150; e.clientY = e.pageY = 40; $sliderBar.trigger(e); - + e = new jQuery.Event('mousedown'); e.clientX = e.pageX = 150; e.clientY = e.pageY = 50; $sliderBar.trigger(e); - + $sliderBar.trigger('mouseup') setTimeout(function() { diff --git a/tests/frontend/specs/timeslider_revisions.js b/tests/frontend/specs/timeslider_revisions.js index 2afd2e9d318..67123344bba 100644 --- a/tests/frontend/specs/timeslider_revisions.js +++ b/tests/frontend/specs/timeslider_revisions.js @@ -6,12 +6,12 @@ describe("timeslider", function(){ }); it("loads adds a hundred revisions", function(done) { // passes - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; + // make some changes to produce 100 revisions var timePerRev = 900 - , revs = 100; + , revs = 99; this.timeout(revs*timePerRev+10000); for(var i=0; i < revs; i++) { setTimeout(function() { @@ -20,43 +20,45 @@ describe("timeslider", function(){ }, timePerRev*i); } chrome$('.buttonicon-savedRevision').click(); - + setTimeout(function() { // go to timeslider $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider'); - + setTimeout(function() { var timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; var $sliderBar = timeslider$('#ui-slider-bar'); - - var latestContents = timeslider$('#padcontent').text(); + + var latestContents = timeslider$('#innerdocbody').text(); // Click somewhere on the timeslider var e = new jQuery.Event('mousedown'); + // sets y co-ordinate of the pad slider modal. + var base = (timeslider$('#ui-slider-bar').offset().top - 24) e.clientX = e.pageX = 150; - e.clientY = e.pageY = 45; + e.clientY = e.pageY = base+5; $sliderBar.trigger(e); - + e = new jQuery.Event('mousedown'); e.clientX = e.pageX = 150; - e.clientY = e.pageY = 40; + e.clientY = e.pageY = base; $sliderBar.trigger(e); - + e = new jQuery.Event('mousedown'); e.clientX = e.pageX = 150; - e.clientY = e.pageY = 50; + e.clientY = e.pageY = base-5; $sliderBar.trigger(e); - + $sliderBar.trigger('mouseup') setTimeout(function() { //make sure the text has changed - expect( timeslider$('#padcontent').text() ).not.to.eql( latestContents ); + expect( timeslider$('#innerdocbody').text() ).not.to.eql( latestContents ); var starIsVisible = timeslider$('.star').is(":visible"); expect( starIsVisible ).to.eql( true ); done(); }, 1000); - + }, 6000); }, revs*timePerRev); }); @@ -64,9 +66,9 @@ describe("timeslider", function(){ // Disabled as jquery trigger no longer works properly xit("changes the url when clicking on the timeslider", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; - + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; + // make some changes to produce 7 revisions var timePerRev = 1000 , revs = 20; @@ -77,24 +79,24 @@ describe("timeslider", function(){ inner$("div").first().sendkeys('a'); }, timePerRev*i); } - + setTimeout(function() { // go to timeslider $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider'); - + setTimeout(function() { var timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; var $sliderBar = timeslider$('#ui-slider-bar'); - - var latestContents = timeslider$('#padcontent').text(); + + var latestContents = timeslider$('#innerdocbody').text(); var oldUrl = $('#iframe-container iframe')[0].contentWindow.location.hash; - + // Click somewhere on the timeslider var e = new jQuery.Event('mousedown'); e.clientX = e.pageX = 150; e.clientY = e.pageY = 60; $sliderBar.trigger(e); - + helper.waitFor(function(){ return $('#iframe-container iframe')[0].contentWindow.location.hash != oldUrl; }, 6000).always(function(){ @@ -105,7 +107,7 @@ describe("timeslider", function(){ }, revs*timePerRev); }); it("jumps to a revision given in the url", function(done) { - var inner$ = helper.padInner$; + var inner$ = helper.padInner$; var chrome$ = helper.padChrome$; this.timeout(20000); @@ -118,7 +120,7 @@ describe("timeslider", function(){ expect( oldLength ).to.not.eql( 0 ); inner$("div").first().sendkeys('a'); var timeslider$; - + // wait for our additional revision to be added helper.waitFor(function(){ // newLines takes the new lines into account which are strippen when using @@ -131,17 +133,17 @@ describe("timeslider", function(){ }, 6000).always(function() { // go to timeslider with a specific revision set $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider#0'); - + // wait for the timeslider to be loaded helper.waitFor(function(){ try { timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; } catch(e){} if(timeslider$){ - return timeslider$('#padcontent').text().length == oldLength; + return timeslider$('#innerdocbody').text().length == oldLength; } }, 6000).always(function(){ - expect( timeslider$('#padcontent').text().length ).to.eql( oldLength ); + expect( timeslider$('#innerdocbody').text().length ).to.eql( oldLength ); done(); }); }); @@ -149,17 +151,17 @@ describe("timeslider", function(){ }); it("checks the export url", function(done) { - var inner$ = helper.padInner$; - var chrome$ = helper.padChrome$; + var inner$ = helper.padInner$; + var chrome$ = helper.padChrome$; this.timeout(11000); inner$("div").first().sendkeys('a'); - + setTimeout(function() { // go to timeslider $('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider#0'); var timeslider$; var exportLink; - + helper.waitFor(function(){ try{ timeslider$ = $('#iframe-container iframe')[0].contentWindow.$; diff --git a/tests/frontend/specs/undo.js b/tests/frontend/specs/undo.js index 3644734f4dd..172a2b81e7b 100644 --- a/tests/frontend/specs/undo.js +++ b/tests/frontend/specs/undo.js @@ -4,11 +4,10 @@ describe("undo button", function(){ this.timeout(60000); }); -/* it("undo some typing by clicking undo button", function(done){ var inner$ = helper.padInner$; var chrome$ = helper.padChrome$; - + // get the first text element inside the editable space var $firstTextElement = inner$("div span").first(); var originalValue = $firstTextElement.text(); // get the original value @@ -30,7 +29,6 @@ describe("undo button", function(){ done(); }); }); -*/ it("undo some typing using a keypress", function(done){ var inner$ = helper.padInner$; @@ -44,13 +42,7 @@ describe("undo button", function(){ var modifiedValue = $firstTextElement.text(); // get the modified value expect(modifiedValue).not.to.be(originalValue); // expect the value to change - /* - * ACHTUNG: this is the only place in the test codebase in which a keydown - * is sent for IE. Everywhere else IE uses keypress. - */ - var evtType = "keydown"; - - var e = inner$.Event(evtType); + var e = inner$.Event(helper.evtType); e.ctrlKey = true; // Control key e.which = 90; // z inner$("#innerdocbody").trigger(e); diff --git a/tests/frontend/specs/unordered_list.js b/tests/frontend/specs/unordered_list.js index 4ea77b8ac7b..8a7fdd7a7b9 100644 --- a/tests/frontend/specs/unordered_list.js +++ b/tests/frontend/specs/unordered_list.js @@ -6,7 +6,7 @@ describe("assign unordered list", function(){ }); it("insert unordered list text then removes by outdent", function(done){ - var inner$ = helper.padInner$; + var inner$ = helper.padInner$; var chrome$ = helper.padChrome$; var originalText = inner$("div").first().text(); diff --git a/tests/frontend/travis/remote_runner.js b/tests/frontend/travis/remote_runner.js index 87311d905d1..09c892f6676 100644 --- a/tests/frontend/travis/remote_runner.js +++ b/tests/frontend/travis/remote_runner.js @@ -67,41 +67,39 @@ var sauceTestWorker = async.queue(function (testSettings, callback) { }); }, 5); //run 5 tests in parrallel -// Firefox +// 1) Firefox on Linux sauceTestWorker.push({ 'platform' : 'Linux' , 'browserName' : 'firefox' - , 'version' : '' + , 'version' : 'latest' }); -// Chrome +// 2) Chrome on Linux sauceTestWorker.push({ 'platform' : 'Linux' , 'browserName' : 'googlechrome' - , 'version' : '' + , 'version' : 'latest' }); -/* -// IE 8 +// 3) Safari on OSX 10.15 sauceTestWorker.push({ - 'platform' : 'Windows 2003' - , 'browserName' : 'iexplore' - , 'version' : '8' + 'platform' : 'OS X 10.15' + , 'browserName' : 'safari' + , 'version' : 'latest' }); -*/ -// IE 9 +// 4) IE 10 on Win 8 sauceTestWorker.push({ - 'platform' : 'Windows XP' + 'platform' : 'Windows 8' , 'browserName' : 'iexplore' - , 'version' : '9' + , 'version' : '10.0' }); -// IE 10 +// 5) Edge on Win 10 sauceTestWorker.push({ - 'platform' : 'Windows 2012' - , 'browserName' : 'iexplore' - , 'version' : '10' + 'platform' : 'Windows 10' + , 'browserName' : 'microsoftedge' + , 'version' : 'latest' }); sauceTestWorker.drain = function() { diff --git a/tests/frontend/travis/runner.sh b/tests/frontend/travis/runner.sh index 1ae5f6ff045..2a4d76bd2aa 100755 --- a/tests/frontend/travis/runner.sh +++ b/tests/frontend/travis/runner.sh @@ -1,13 +1,48 @@ -#!/bin/sh +#!/bin/bash +if [ -z "${SAUCE_USERNAME}" ]; then echo "SAUCE_USERNAME is unset - exiting"; exit 1; fi +if [ -z "${SAUCE_ACCESS_KEY}" ]; then echo "SAUCE_ACCESS_KEY is unset - exiting"; exit 1; fi -#Move to the base folder -cd `dirname $0` +# do not continue if there is an error +set -eu -#start Etherpad -../../../bin/run.sh > /dev/null & -sleep 10 +# source: https://stackoverflow.com/questions/59895/get-the-source-directory-of-a-bash-script-from-within-the-script-itself#246128 +MY_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" -#start remote runner +# reliably move to the etherpad base folder before running it +cd "${MY_DIR}/../../../" + +# start Etherpad, assuming all dependencies are already installed. +# +# This is possible because the "install" section of .travis.yml already contains +# a call to bin/installDeps.sh +echo "Running Etherpad directly, assuming bin/installDeps.sh has already been run" +node node_modules/ep_etherpad-lite/node/server.js "${@}" > /dev/null & + +echo "Now I will try for 15 seconds to connect to Etherpad on http://localhost:9001" + +# wait for at most 15 seconds until Etherpad starts accepting connections +# +# modified from: +# https://unix.stackexchange.com/questions/5277/how-do-i-tell-a-script-to-wait-for-a-process-to-start-accepting-requests-on-a-po#349138 +# +(timeout 15 bash -c 'until echo > /dev/tcp/localhost/9001; do sleep 0.5; done') || \ + (echo "Could not connect to Etherpad on http://localhost:9001" ; exit 1) + +echo "Successfully connected to Etherpad on http://localhost:9001" + +# just in case, let's wait for another second before going on +sleep 1 + +# On the Travis VM, remote_runner.js is found at +# /home/travis/build/ether/[secure]/tests/frontend/travis/remote_runner.js +# which is the same directory that contains this script. +# Let's move back there. +# +# Probably remote_runner.js is injected by Saucelabs. +cd "${MY_DIR}" + +# start the remote runner +echo "Now starting the remote runner" node remote_runner.js exit_code=$? @@ -15,4 +50,4 @@ kill $! kill $(cat /tmp/sauce.pid) sleep 30 -exit $exit_code \ No newline at end of file +exit $exit_code diff --git a/tests/frontend/travis/runnerBackend.sh b/tests/frontend/travis/runnerBackend.sh new file mode 100755 index 00000000000..50e5ce36b77 --- /dev/null +++ b/tests/frontend/travis/runnerBackend.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +# do not continue if there is an error +set -eu + +# source: https://stackoverflow.com/questions/59895/get-the-source-directory-of-a-bash-script-from-within-the-script-itself#246128 +MY_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" + +# reliably move to the etherpad base folder before running it +cd "${MY_DIR}/../../../" + +# start Etherpad, assuming all dependencies are already installed. +# +# This is possible because the "install" section of .travis.yml already contains +# a call to bin/installDeps.sh +echo "Running Etherpad directly, assuming bin/installDeps.sh has already been run" +node node_modules/ep_etherpad-lite/node/server.js "${@}" > /dev/null & + +echo "Now I will try for 15 seconds to connect to Etherpad on http://localhost:9001" + +# wait for at most 15 seconds until Etherpad starts accepting connections +# +# modified from: +# https://unix.stackexchange.com/questions/5277/how-do-i-tell-a-script-to-wait-for-a-process-to-start-accepting-requests-on-a-po#349138 +# +(timeout 15 bash -c 'until echo > /dev/tcp/localhost/9001; do sleep 0.5; done') || \ + (echo "Could not connect to Etherpad on http://localhost:9001" ; exit 1) + +echo "Successfully connected to Etherpad on http://localhost:9001" + +# just in case, let's wait for another second before going on +sleep 1 + +# a copy of settings.json is necessary for the backend tests to work +cp settings.json.template settings.json + +# run the backend tests +echo "Now run the backend tests" +cd src +npm run test +exit_code=$? + +kill $! +sleep 5 + +exit $exit_code diff --git a/tests/frontend/travis/sauce_tunnel.sh b/tests/frontend/travis/sauce_tunnel.sh index b19268d0583..b8e1bc59e58 100755 --- a/tests/frontend/travis/sauce_tunnel.sh +++ b/tests/frontend/travis/sauce_tunnel.sh @@ -1,11 +1,20 @@ #!/bin/bash # download and unzip the sauce connector -curl https://saucelabs.com/downloads/sc-latest-linux.tar.gz > /tmp/sauce.tar.gz +# +# ACHTUNG: as of 2019-12-21, downloading sc-latest-linux.tar.gz does not work. +# It is necessary to explicitly download a specific version, for +# example https://saucelabs.com/downloads/sc-4.5.4-linux.tar.gz +# Supported versions are currently listed at: +# https://wiki.saucelabs.com/display/DOCS/Downloading+Sauce+Connect+Proxy +if [ -z "${SAUCE_USERNAME}" ]; then echo "SAUCE_USERNAME is unset - exiting"; exit 1; fi +if [ -z "${SAUCE_ACCESS_KEY}" ]; then echo "SAUCE_ACCESS_KEY is unset - exiting"; exit 1; fi + +curl https://saucelabs.com/downloads/sc-4.5.4-linux.tar.gz > /tmp/sauce.tar.gz tar zxf /tmp/sauce.tar.gz --directory /tmp mv /tmp/sc-*-linux /tmp/sauce_connect # start the sauce connector in background and make sure it doesn't output the secret key -(/tmp/sauce_connect/bin/sc --user $SAUCE_USERNAME --key $SAUCE_ACCESS_KEY --pidfile /tmp/sauce.pid --readyfile /tmp/tunnel > /dev/null )& +(/tmp/sauce_connect/bin/sc --user "${SAUCE_USERNAME}" --key "${SAUCE_ACCESS_KEY}" --pidfile /tmp/sauce.pid --readyfile /tmp/tunnel > /dev/null )& # wait for the tunnel to build up while [ ! -e "/tmp/tunnel" ]