瀏覽代碼

merge multiple repositories into a monorepo

- merged using: 'monorepo_build.sh main-repository package-ckeditor-cloud-services-core:packages/ckeditor-cloud-services-core package-ckeditor5-adapter-ckfinder:packages/ckeditor5-adapter-ckfinder package-ckeditor5-alignment:packages/ckeditor5-alignment package-ckeditor5-autoformat:packages/ckeditor5-autoformat package-ckeditor5-autosave:packages/ckeditor5-autosave package-ckeditor5-basic-styles:packages/ckeditor5-basic-styles package-ckeditor5-block-quote:packages/ckeditor5-block-quote package-ckeditor5-build-balloon:packages/ckeditor5-build-balloon package-ckeditor5-build-balloon-block:packages/ckeditor5-build-balloon-block package-ckeditor5-build-classic:packages/ckeditor5-build-classic package-ckeditor5-build-decoupled-document:packages/ckeditor5-build-decoupled-document package-ckeditor5-build-inline:packages/ckeditor5-build-inline package-ckeditor5-ckfinder:packages/ckeditor5-ckfinder package-ckeditor5-clipboard:packages/ckeditor5-clipboard package-ckeditor5-cloud-services:packages/ckeditor5-cloud-services package-ckeditor5-code-block:packages/ckeditor5-code-block package-ckeditor5-core:packages/ckeditor5-core package-ckeditor5-easy-image:packages/ckeditor5-easy-image package-ckeditor5-editor-balloon:packages/ckeditor5-editor-balloon package-ckeditor5-editor-classic:packages/ckeditor5-editor-classic package-ckeditor5-editor-decoupled:packages/ckeditor5-editor-decoupled package-ckeditor5-editor-inline:packages/ckeditor5-editor-inline package-ckeditor5-engine:packages/ckeditor5-engine package-ckeditor5-enter:packages/ckeditor5-enter package-ckeditor5-essentials:packages/ckeditor5-essentials package-ckeditor5-font:packages/ckeditor5-font package-ckeditor5-heading:packages/ckeditor5-heading package-ckeditor5-highlight:packages/ckeditor5-highlight package-ckeditor5-horizontal-line:packages/ckeditor5-horizontal-line package-ckeditor5-image:packages/ckeditor5-image package-ckeditor5-indent:packages/ckeditor5-indent package-ckeditor5-link:packages/ckeditor5-link package-ckeditor5-list:packages/ckeditor5-list package-ckeditor5-markdown-gfm:packages/ckeditor5-markdown-gfm package-ckeditor5-media-embed:packages/ckeditor5-media-embed package-ckeditor5-mention:packages/ckeditor5-mention package-ckeditor5-page-break:packages/ckeditor5-page-break package-ckeditor5-paragraph:packages/ckeditor5-paragraph package-ckeditor5-paste-from-office:packages/ckeditor5-paste-from-office package-ckeditor5-remove-format:packages/ckeditor5-remove-format package-ckeditor5-restricted-editing:packages/ckeditor5-restricted-editing package-ckeditor5-select-all:packages/ckeditor5-select-all package-ckeditor5-special-characters:packages/ckeditor5-special-characters package-ckeditor5-table:packages/ckeditor5-table package-ckeditor5-theme-lark:packages/ckeditor5-theme-lark package-ckeditor5-typing:packages/ckeditor5-typing package-ckeditor5-ui:packages/ckeditor5-ui package-ckeditor5-undo:packages/ckeditor5-undo package-ckeditor5-upload:packages/ckeditor5-upload package-ckeditor5-utils:packages/ckeditor5-utils package-ckeditor5-watchdog:packages/ckeditor5-watchdog package-ckeditor5-widget:packages/ckeditor5-widget package-ckeditor5-word-count:packages/ckeditor5-word-count'
- see https://github.com/shopsys/monorepo-tools
共有 100 個文件被更改,包括 3529 次插入0 次删除
  1. 16 0
      packages/ckeditor-cloud-services-core/.editorconfig
  2. 12 0
      packages/ckeditor-cloud-services-core/.eslintrc.js
  3. 18 0
      packages/ckeditor-cloud-services-core/.gitattributes
  4. 9 0
      packages/ckeditor-cloud-services-core/.github/PULL_REQUEST_TEMPLATE.md
  5. 4 0
      packages/ckeditor-cloud-services-core/.gitignore
  6. 3 0
      packages/ckeditor-cloud-services-core/.stylelintrc
  7. 31 0
      packages/ckeditor-cloud-services-core/.travis.yml
  8. 28 0
      packages/ckeditor-cloud-services-core/CHANGELOG.md
  9. 4 0
      packages/ckeditor-cloud-services-core/CONTRIBUTING.md
  10. 17 0
      packages/ckeditor-cloud-services-core/LICENSE.md
  11. 14 0
      packages/ckeditor-cloud-services-core/README.md
  12. 28 0
      packages/ckeditor-cloud-services-core/docs/api/cloud-services-core.md
  13. 58 0
      packages/ckeditor-cloud-services-core/package.json
  14. 202 0
      packages/ckeditor-cloud-services-core/src/token/token.js
  15. 291 0
      packages/ckeditor-cloud-services-core/src/uploadgateway/fileuploader.js
  16. 78 0
      packages/ckeditor-cloud-services-core/src/uploadgateway/uploadgateway.js
  17. 263 0
      packages/ckeditor-cloud-services-core/tests/token/token.js
  18. 223 0
      packages/ckeditor-cloud-services-core/tests/uploadgateway/fileuploader.js
  19. 31 0
      packages/ckeditor-cloud-services-core/tests/uploadgateway/uploadgateway.js
  20. 16 0
      packages/ckeditor5-adapter-ckfinder/.editorconfig
  21. 12 0
      packages/ckeditor5-adapter-ckfinder/.eslintrc.js
  22. 18 0
      packages/ckeditor5-adapter-ckfinder/.gitattributes
  23. 9 0
      packages/ckeditor5-adapter-ckfinder/.github/PULL_REQUEST_TEMPLATE.md
  24. 1 0
      packages/ckeditor5-adapter-ckfinder/.gitignore
  25. 3 0
      packages/ckeditor5-adapter-ckfinder/.stylelintrc
  26. 31 0
      packages/ckeditor5-adapter-ckfinder/.travis.yml
  27. 157 0
      packages/ckeditor5-adapter-ckfinder/CHANGELOG.md
  28. 4 0
      packages/ckeditor5-adapter-ckfinder/CONTRIBUTING.md
  29. 17 0
      packages/ckeditor5-adapter-ckfinder/LICENSE.md
  30. 18 0
      packages/ckeditor5-adapter-ckfinder/README.md
  31. 32 0
      packages/ckeditor5-adapter-ckfinder/docs/api/adapter-ckfinder.md
  32. 3 0
      packages/ckeditor5-adapter-ckfinder/lang/contexts.json
  33. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/af.po
  34. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/ar.po
  35. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/az.po
  36. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/ca.po
  37. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/cs.po
  38. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/da.po
  39. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/de-ch.po
  40. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/de.po
  41. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/en-au.po
  42. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/en-gb.po
  43. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/en.po
  44. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/es.po
  45. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/et.po
  46. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/eu.po
  47. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/fa.po
  48. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/fi.po
  49. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/fr.po
  50. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/gl.po
  51. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/gu.po
  52. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/he.po
  53. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/hr.po
  54. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/hu.po
  55. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/id.po
  56. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/it.po
  57. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/ja.po
  58. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/km.po
  59. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/ko.po
  60. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/ku.po
  61. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/lt.po
  62. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/lv.po
  63. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/ms.po
  64. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/nb.po
  65. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/ne.po
  66. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/nl.po
  67. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/no.po
  68. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/pl.po
  69. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/pt-br.po
  70. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/pt.po
  71. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/ro.po
  72. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/ru.po
  73. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/si.po
  74. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/sk.po
  75. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/sl.po
  76. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/sq.po
  77. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/sr-latn.po
  78. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/sr.po
  79. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/sv.po
  80. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/th.po
  81. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/tr.po
  82. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/ug.po
  83. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/uk.po
  84. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/vi.po
  85. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/zh-cn.po
  86. 21 0
      packages/ckeditor5-adapter-ckfinder/lang/translations/zh.po
  87. 72 0
      packages/ckeditor5-adapter-ckfinder/package.json
  88. 189 0
      packages/ckeditor5-adapter-ckfinder/src/uploadadapter.js
  89. 83 0
      packages/ckeditor5-adapter-ckfinder/src/utils.js
  90. 4 0
      packages/ckeditor5-adapter-ckfinder/tests/manual/uploadadapter.html
  91. 42 0
      packages/ckeditor5-adapter-ckfinder/tests/manual/uploadadapter.js
  92. 10 0
      packages/ckeditor5-adapter-ckfinder/tests/manual/uploadadapter.md
  93. 213 0
      packages/ckeditor5-adapter-ckfinder/tests/uploadadapter.js
  94. 72 0
      packages/ckeditor5-adapter-ckfinder/tests/utils.js
  95. 16 0
      packages/ckeditor5-alignment/.editorconfig
  96. 12 0
      packages/ckeditor5-alignment/.eslintrc.js
  97. 18 0
      packages/ckeditor5-alignment/.gitattributes
  98. 9 0
      packages/ckeditor5-alignment/.github/PULL_REQUEST_TEMPLATE.md
  99. 1 0
      packages/ckeditor5-alignment/.gitignore
  100. 3 0
      packages/ckeditor5-alignment/.stylelintrc

+ 16 - 0
packages/ckeditor-cloud-services-core/.editorconfig

@@ -0,0 +1,16 @@
+# Configurations to normalize the IDE behavior.
+# http://editorconfig.org/
+
+root = true
+
+[*]
+indent_style = tab
+tab_width = 4
+charset = utf-8
+end_of_line = lf
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[package.json]
+indent_style = space
+tab_width = 2

+ 12 - 0
packages/ckeditor-cloud-services-core/.eslintrc.js

@@ -0,0 +1,12 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/* eslint-env node */
+
+'use strict';
+
+module.exports = {
+	extends: 'ckeditor5'
+};

+ 18 - 0
packages/ckeditor-cloud-services-core/.gitattributes

@@ -0,0 +1,18 @@
+*			text=auto
+
+*.htaccess	eol=lf
+*.cgi		eol=lf
+*.sh		eol=lf
+
+*.css		text
+*.htm		text
+*.html		text
+*.js		text
+*.json		text
+*.php		text
+*.txt		text
+*.md		text
+
+*.png		-text
+*.gif		-text
+*.jpg		-text

+ 9 - 0
packages/ckeditor-cloud-services-core/.github/PULL_REQUEST_TEMPLATE.md

@@ -0,0 +1,9 @@
+### Suggested merge commit message ([convention](https://github.com/ckeditor/ckeditor5-design/wiki/Git-commit-message-convention))
+
+Type: Message. Closes ckeditor/ckeditor5#000.
+
+---
+
+### Additional information
+
+*For example – encountered issues, assumptions you had to make, other affected tickets, etc.*

+ 4 - 0
packages/ckeditor-cloud-services-core/.gitignore

@@ -0,0 +1,4 @@
+node_modules
+coverage
+.idea
+package-lock.json

+ 3 - 0
packages/ckeditor-cloud-services-core/.stylelintrc

@@ -0,0 +1,3 @@
+{
+	"extends": "stylelint-config-ckeditor5"
+}

+ 31 - 0
packages/ckeditor-cloud-services-core/.travis.yml

@@ -0,0 +1,31 @@
+sudo: required
+dist: xenial
+addons:
+  chrome: stable
+  firefox: latest
+language: node_js
+services:
+- xvfb
+node_js:
+- '10'
+cache:
+  yarn: true
+branches:
+  except:
+  - stable
+before_install:
+- export START_TIME=$( date +%s )
+- npm i -g yarn
+install:
+- yarn add @ckeditor/ckeditor5-dev-tests
+- ckeditor5-dev-tests-install-dependencies
+script:
+- ckeditor5-dev-tests-travis
+after_script:
+- export END_TIME=$( date +%s )
+- ckeditor5-dev-tests-notify-travis-status
+after_success:
+- ckeditor5-dev-tests-save-revision
+env:
+  global:
+  - secure: NEc7V0b4XaZfCzk8pne6dLV9wsM036yb9C+rkrXORQJuBHP7k93b5jcXzLvqE1LbZwyoWVroAmOKBR+0+ZoqcfcTU49dL6W3kmdbJr6ltxHHqcJ+9ES7bdxOMxuu7Uy+EQrdKOOfxh6MPOPQC6+d3bAwiMYuzM1yUtif7oYuFMsR7aRqQreWVnpiJPy4+EDOGmEw+WHgr9vms3RsK4dyECbnLYaCBsK0IAzYh94wKz7/NCBYANExojKuvKNBQvonjz/tMW/2y/9MS5+N8il9H/skzkgbB2jkwaC9Ved2m41TCVaPWg1DBLvN/T/bcD3br4a6r71V9QiDxS12qcc/gtlpKKByAiYMu8clhrBgda9PGGxuAAVeJwcAzcw6SMfoAaymSuhZQDfKiHdFBu4cxCjRFL7SkN5ReBRZfRaYfxuN66Lftd3rukwiz3xFX1XlXpqDPQQlgKm0KbLQZro1M3qaRgUc01kp+JLyDElLs/3sgWjJfof2+V5+kNSSoni5W9VOVg7+5ukPxVaGpY40B5nL0T5WcE5U4xrOaoyQsBwuyJSpxdSQ2N2NP7mJ5NyX6zaLAc2MGsIbNftygOWwJIVZ4rCVMp3NP3bc9BDlMHenWINzVpfh3x2Sy1TI8yDgfjYGjMxwGkkXzz8NzvOHFJ35Y4q9T/d0yLXoZS+XupM=

+ 28 - 0
packages/ckeditor-cloud-services-core/CHANGELOG.md

@@ -0,0 +1,28 @@
+Changelog
+=========
+
+## [19.0.0](https://github.com/ckeditor/ckeditor-cloud-services-core/compare/v18.0.0...v19.0.0) (2020-04-29)
+
+### Features
+
+* Exposed the `refreshToken` method. ([013b89e](https://github.com/ckeditor/ckeditor-cloud-services-core/commit/013b89e))
+
+
+## [18.0.0](https://github.com/ckeditor/ckeditor-cloud-services-core/compare/v17.0.0...v18.0.0) (2020-03-19)
+
+Internal changes only (updated dependencies, documentation, etc.).
+
+
+## [17.0.0](https://github.com/ckeditor/ckeditor-cloud-services-core/compare/v16.0.0...v17.0.0) (2020-02-18)
+
+Internal changes only (updated dependencies, documentation, etc.).
+
+
+## [16.0.0](https://github.com/ckeditor/ckeditor-cloud-services-core/compare/v15.0.0...v16.0.0) (2019-12-04)
+
+Internal changes only (updated dependencies, documentation, etc.).
+
+
+## [15.0.0](https://github.com/ckeditor/ckeditor-cloud-services-core/compare/v3.0.1...v15.0.0) (2019-10-23)
+
+First release tracked in the changelog.

+ 4 - 0
packages/ckeditor-cloud-services-core/CONTRIBUTING.md

@@ -0,0 +1,4 @@
+Contributing
+========================================
+
+See the [official contributors' guide to CKEditor 5](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html) to learn more.

+ 17 - 0
packages/ckeditor-cloud-services-core/LICENSE.md

@@ -0,0 +1,17 @@
+Software License Agreement
+==========================
+
+**CKEditor Cloud Services Core** – https://github.com/ckeditor/ckeditor-cloud-services-core <br>
+Copyright (c) 2003-2020, [CKSource](http://cksource.com) Frederico Knabben. All rights reserved.
+
+Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).
+
+Sources of Intellectual Property Included in CKEditor Cloud Services Core
+-------------------------------------------------------------------------
+
+Where not otherwise indicated, all CKEditor Cloud Services Core content is authored by CKSource engineers and consists of CKSource-owned intellectual property. In some specific instances, CKEditor Cloud Services Core will incorporate work done by developers outside of CKSource with their express permission.
+
+Trademarks
+----------
+
+**CKEditor** is a trademark of [CKSource](http://cksource.com) Frederico Knabben. All other brand and product names are trademarks, registered trademarks or service marks of their respective holders.

+ 14 - 0
packages/ckeditor-cloud-services-core/README.md

@@ -0,0 +1,14 @@
+CKEditor Cloud Services Core
+============================
+
+[![npm version](https://badge.fury.io/js/%40ckeditor%2Fckeditor-cloud-services-core.svg)](https://www.npmjs.com/package/@ckeditor/ckeditor-cloud-services-core)
+[![Dependency Status](https://david-dm.org/ckeditor/ckeditor-cloud-services-core/status.svg)](https://david-dm.org/ckeditor/ckeditor-cloud-services-core)
+[![devDependency Status](https://david-dm.org/ckeditor/ckeditor-cloud-services-core/dev-status.svg)](https://david-dm.org/ckeditor/ckeditor-cloud-services-core?type=dev)
+
+## Documentation
+
+See the [`@ckeditor/ckeditor-cloud-services-core` package](https://ckeditor.com/docs/ckeditor5/latest/api/cloud-services-core.html) page in [CKEditor 5 documentation](https://ckeditor.com/docs/ckeditor5/latest/).
+
+## License
+
+Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html). For full details about the license, please check the `LICENSE.md` file or [https://ckeditor.com/legal/ckeditor-oss-license](https://ckeditor.com/legal/ckeditor-oss-license).

+ 28 - 0
packages/ckeditor-cloud-services-core/docs/api/cloud-services-core.md

@@ -0,0 +1,28 @@
+---
+category: api-reference
+---
+
+# CKEditor 5 Cloud Services Core
+
+[![npm version](https://badge.fury.io/js/%40ckeditor%2Fckeditor-cloud-services-core.svg)](https://www.npmjs.com/package/@ckeditor/ckeditor-cloud-services-core)
+
+CKEditor Cloud Services Core API:
+
+* {@link module:cloud-services-core/uploadgateway/uploadgateway~UploadGateway Upload Gateway} &mdash; API for file uploads to CKEditor Cloud Services.
+
+## Installation
+
+```bash
+npm install --save @ckeditor/ckeditor-cloud-services-core
+```
+
+## Contribute
+
+The source code of this package is available on GitHub in https://github.com/ckeditor/ckeditor5/tree/master/packages/ckeditor-cloud-services-core.
+
+## External links
+
+* [`@ckeditor/ckeditor-cloud-services-core` on npm](https://www.npmjs.com/package/@ckeditor/ckeditor-cloud-services-core)
+* [`ckeditor/ckeditor-cloud-services-core` on GitHub](https://github.com/ckeditor/ckeditor5/tree/master/packages/ckeditor-cloud-services-core)
+* [Issue tracker](https://github.com/ckeditor/ckeditor5/issues)
+* [Changelog](https://github.com/ckeditor/ckeditor-cloud-services-core/blob/master/CHANGELOG.md)

+ 58 - 0
packages/ckeditor-cloud-services-core/package.json

@@ -0,0 +1,58 @@
+{
+  "name": "@ckeditor/ckeditor-cloud-services-core",
+  "version": "19.0.0",
+  "description": "CKEditor Cloud Services Core API.",
+  "keywords": [
+    "ckeditor5",
+    "ckeditor5-lib"
+  ],
+  "dependencies": {
+    "@ckeditor/ckeditor5-utils": "^19.0.0"
+  },
+  "devDependencies": {
+    "eslint": "^5.5.0",
+    "eslint-config-ckeditor5": "^2.0.0",
+    "husky": "^1.3.1",
+    "lint-staged": "^7.0.0",
+    "stylelint": "^11.1.1",
+    "stylelint-config-ckeditor5": "^1.0.0"
+  },
+  "engines": {
+    "node": ">=8.0.0",
+    "npm": ">=5.7.1"
+  },
+  "author": "CKSource (http://cksource.com/)",
+  "license": "GPL-2.0-or-later",
+  "homepage": "https://ckeditor.com",
+  "bugs": "https://github.com/ckeditor/ckeditor5/issues",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/ckeditor/ckeditor-cloud-services-core.git"
+  },
+  "files": [
+    "lang",
+    "src",
+    "theme"
+  ],
+  "scripts": {
+    "lint": "eslint --quiet '**/*.js'",
+    "stylelint": "stylelint --quiet --allow-empty-input 'theme/**/*.css' 'docs/**/*.css'"
+  },
+  "lint-staged": {
+    "**/*.js": [
+      "eslint --quiet"
+    ],
+    "**/*.css": [
+      "stylelint --quiet --allow-empty-input"
+    ]
+  },
+  "eslintIgnore": [
+    "src/lib/**",
+    "packages/**"
+  ],
+  "husky": {
+    "hooks": {
+      "pre-commit": "lint-staged"
+    }
+  }
+}

+ 202 - 0
packages/ckeditor-cloud-services-core/src/token/token.js

@@ -0,0 +1,202 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module cloud-services-core/token
+ */
+
+/* globals XMLHttpRequest, setInterval, clearInterval */
+
+import mix from '@ckeditor/ckeditor5-utils/src/mix';
+import ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';
+import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
+
+const DEFAULT_OPTIONS = { refreshInterval: 3600000, autoRefresh: true };
+
+/**
+ * Class representing the token used for communication with CKEditor Cloud Services.
+ * Value of the token is retrieving from the specified URL and is refreshed every 1 hour by default.
+ *
+ * @mixes ObservableMixin
+ */
+class Token {
+	/**
+	 * Creates `Token` instance.
+	 * Method `init` should be called after using the constructor or use `create` method instead.
+	 *
+	 * @param {String|Function} tokenUrlOrRefreshToken Endpoint address to download the token or a callback that provides the token. If the
+	 * value is a function it has to match the {@link module:cloud-services-core/token~refreshToken} interface.
+	 * @param {Object} options
+	 * @param {String} [options.initValue] Initial value of the token.
+	 * @param {Number} [options.refreshInterval=3600000] Delay between refreshes. Default 1 hour.
+	 * @param {Boolean} [options.autoRefresh=true] Specifies whether to start the refresh automatically.
+	 */
+	constructor( tokenUrlOrRefreshToken, options = DEFAULT_OPTIONS ) {
+		if ( !tokenUrlOrRefreshToken ) {
+			/**
+			 * A `tokenUrl` must be provided as the first constructor argument.
+			 *
+			 * @error token-missing-token-url
+			 */
+			throw new CKEditorError(
+				'token-missing-token-url: A `tokenUrl` must be provided as the first constructor argument.',
+				this
+			);
+		}
+
+		/**
+		 * Value of the token.
+		 * The value of the token is null if `initValue` is not provided or `init` method was not called.
+		 * `create` method creates token with initialized value from url.
+		 *
+		 * @name value
+		 * @member {String} #value
+		 * @observable
+		 * @readonly
+		 */
+		this.set( 'value', options.initValue );
+
+		/**
+		 * Base refreshing function.
+		 *
+		 * @private
+		 * @member {String|Function} #_refresh
+		 */
+		if ( typeof tokenUrlOrRefreshToken === 'function' ) {
+			this._refresh = tokenUrlOrRefreshToken;
+		} else {
+			this._refresh = () => defaultRefreshToken( tokenUrlOrRefreshToken );
+		}
+
+		/**
+		 * @type {Object}
+		 * @private
+		 */
+		this._options = Object.assign( {}, DEFAULT_OPTIONS, options );
+	}
+
+	/**
+	 * Initializes the token.
+	 *
+	 * @returns {Promise.<module:cloud-services-core/token~Token>}
+	 */
+	init() {
+		return new Promise( ( resolve, reject ) => {
+			if ( this._options.autoRefresh ) {
+				this._startRefreshing();
+			}
+
+			if ( !this.value ) {
+				this.refreshToken()
+					.then( resolve )
+					.catch( reject );
+
+				return;
+			}
+
+			resolve( this );
+		} );
+	}
+
+	/**
+	 * Refresh token method. Useful in a method form as it can be override in tests.
+	 * @returns {Promise.<String>}
+	 */
+	refreshToken() {
+		return this._refresh()
+			.then( value => this.set( 'value', value ) )
+			.then( () => this );
+	}
+
+	/**
+	 * Destroys token instance. Stops refreshing.
+	 */
+	destroy() {
+		this._stopRefreshing();
+	}
+
+	/**
+	 * Starts value refreshing every `refreshInterval` time.
+	 *
+	 * @protected
+	 */
+	_startRefreshing() {
+		this._refreshInterval = setInterval( () => this.refreshToken(), this._options.refreshInterval );
+	}
+
+	/**
+	 * Stops value refreshing.
+	 *
+	 * @protected
+	 */
+	_stopRefreshing() {
+		clearInterval( this._refreshInterval );
+	}
+
+	/**
+	 * Creates a initialized {@link module:cloud-services-core/token~Token} instance.
+	 *
+	 * @param {String|Function} tokenUrlOrRefreshToken Endpoint address to download the token or a callback that provides the token. If the
+	 * value is a function it has to match the {@link module:cloud-services-core/token~refreshToken} interface.
+	 * @param {Object} options
+	 * @param {String} [options.initValue] Initial value of the token.
+	 * @param {Number} [options.refreshInterval=3600000] Delay between refreshes. Default 1 hour.
+	 * @param {Boolean} [options.autoRefresh=true] Specifies whether to start the refresh automatically.
+	 * @returns {Promise.<module:cloud-services-core/token~Token>}
+	 */
+	static create( tokenUrlOrRefreshToken, options = DEFAULT_OPTIONS ) {
+		const token = new Token( tokenUrlOrRefreshToken, options );
+
+		return token.init();
+	}
+}
+
+mix( Token, ObservableMixin );
+
+/**
+ * This function is called in a defined interval by the {@link ~Token} class. It also can be invoked manually.
+ * It should return a promise, which resolves with the new token value.
+ * If any error occurs it should return a rejected promise with an error message.
+ *
+ * @function refreshToken
+ * @returns {Promise.<String>}
+ */
+
+/**
+ * @private
+ * @param {String} tokenUrl
+ */
+function defaultRefreshToken( tokenUrl ) {
+	return new Promise( ( resolve, reject ) => {
+		const xhr = new XMLHttpRequest();
+
+		xhr.open( 'GET', tokenUrl );
+
+		xhr.addEventListener( 'load', () => {
+			const statusCode = xhr.status;
+			const xhrResponse = xhr.response;
+
+			if ( statusCode < 200 || statusCode > 299 ) {
+				/**
+				 * Cannot download new token from the provided url.
+				 *
+				 * @error token-cannot-download-new-token
+				 */
+				return reject(
+					new CKEditorError( 'token-cannot-download-new-token: Cannot download new token from the provided url.', null )
+				);
+			}
+
+			return resolve( xhrResponse );
+		} );
+
+		xhr.addEventListener( 'error', () => reject( new Error( 'Network Error' ) ) );
+		xhr.addEventListener( 'abort', () => reject( new Error( 'Abort' ) ) );
+
+		xhr.send();
+	} );
+}
+
+export default Token;

+ 291 - 0
packages/ckeditor-cloud-services-core/src/uploadgateway/fileuploader.js

@@ -0,0 +1,291 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module cloud-services-core/uploadgateway/fileuploader
+ */
+
+/* globals XMLHttpRequest, FormData, Blob, atob */
+
+import mix from '@ckeditor/ckeditor5-utils/src/mix';
+import EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';
+import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
+
+const BASE64_HEADER_REG_EXP = /^data:(\S*?);base64,/;
+
+/**
+ * FileUploader class used to upload single file.
+ */
+export default class FileUploader {
+	/**
+	 * Creates `FileUploader` instance.
+	 *
+	 * @param {Blob|String} fileOrData A blob object or a data string encoded with Base64.
+	 * @param {module:cloud-services-core/token~Token} token Token used for authentication.
+	 * @param {String} apiAddress API address.
+	 */
+	constructor( fileOrData, token, apiAddress ) {
+		if ( !fileOrData ) {
+			/**
+			 * File must be provided as the first argument.
+			 *
+			 * @error fileuploader-missing-file
+			 */
+			throw new CKEditorError( 'fileuploader-missing-file: File must be provided as the first argument', null );
+		}
+
+		if ( !token ) {
+			/**
+			 * Token must be provided as the second argument.
+			 *
+			 * @error fileuploader-missing-token
+			 */
+			throw new CKEditorError( 'fileuploader-missing-token: Token must be provided as the second argument.', null );
+		}
+
+		if ( !apiAddress ) {
+			/**
+			 * Api address must be provided as the third argument.
+			 *
+			 * @error fileuploader-missing-api-address
+			 */
+			throw new CKEditorError( 'fileuploader-missing-api-address: Api address must be provided as the third argument.', null );
+		}
+
+		/**
+		 * A file that is being uploaded.
+		 *
+		 * @type {Blob}
+		 */
+		this.file = _isBase64( fileOrData ) ? _base64ToBlob( fileOrData ) : fileOrData;
+
+		/**
+		 * CKEditor Cloud Services access token.
+		 *
+		 * @type {module:cloud-services-core/token~Token}
+		 * @private
+		 */
+		this._token = token;
+
+		/**
+		 * CKEditor Cloud Services API address.
+		 *
+		 * @type {String}
+		 * @private
+		 */
+		this._apiAddress = apiAddress;
+	}
+
+	/**
+	 * Registers callback on `progress` event.
+	 *
+	 * @chainable
+	 * @param {Function} callback
+	 * @returns {module:cloud-services-core/uploadgateway/fileuploader~FileUploader}
+	 */
+	onProgress( callback ) {
+		this.on( 'progress', ( event, data ) => callback( data ) );
+
+		return this;
+	}
+
+	/**
+	 * Registers callback on `error` event. Event is called once when error occurs.
+	 *
+	 * @chainable
+	 * @param {Function} callback
+	 * @returns {module:cloud-services-core/uploadgateway/fileuploader~FileUploader}
+	 */
+	onError( callback ) {
+		this.once( 'error', ( event, data ) => callback( data ) );
+
+		return this;
+	}
+
+	/**
+	 * Aborts upload process.
+	 */
+	abort() {
+		this.xhr.abort();
+	}
+
+	/**
+	 * Sends XHR request to API.
+	 *
+	 * @chainable
+	 * @returns {Promise.<Object>}
+	 */
+	send() {
+		this._prepareRequest();
+		this._attachXHRListeners();
+
+		return this._sendRequest();
+	}
+
+	/**
+	 * Prepares XHR request.
+	 *
+	 * @private
+	 */
+	_prepareRequest() {
+		const xhr = new XMLHttpRequest();
+
+		xhr.open( 'POST', this._apiAddress );
+		xhr.setRequestHeader( 'Authorization', this._token.value );
+		xhr.responseType = 'json';
+
+		this.xhr = xhr;
+	}
+
+	/**
+	 * Attaches listeners to the XHR.
+	 *
+	 * @private
+	 */
+	_attachXHRListeners() {
+		const that = this;
+		const xhr = this.xhr;
+
+		xhr.addEventListener( 'error', onError( 'Network Error' ) );
+		xhr.addEventListener( 'abort', onError( 'Abort' ) );
+
+		/* istanbul ignore else */
+		if ( xhr.upload ) {
+			xhr.upload.addEventListener( 'progress', event => {
+				if ( event.lengthComputable ) {
+					this.fire( 'progress', {
+						total: event.total,
+						uploaded: event.loaded
+					} );
+				}
+			} );
+		}
+
+		xhr.addEventListener( 'load', () => {
+			const statusCode = xhr.status;
+			const xhrResponse = xhr.response;
+
+			if ( statusCode < 200 || statusCode > 299 ) {
+				return this.fire( 'error', xhrResponse.message || xhrResponse.error );
+			}
+		} );
+
+		function onError( message ) {
+			return () => that.fire( 'error', message );
+		}
+	}
+
+	/**
+	 * Sends XHR request.
+	 *
+	 * @private
+	 */
+	_sendRequest() {
+		const formData = new FormData();
+		const xhr = this.xhr;
+
+		formData.append( 'file', this.file );
+
+		return new Promise( ( resolve, reject ) => {
+			xhr.addEventListener( 'load', () => {
+				const statusCode = xhr.status;
+				const xhrResponse = xhr.response;
+
+				if ( statusCode < 200 || statusCode > 299 ) {
+					if ( xhrResponse.message ) {
+						/**
+						 * Uploading file failed.
+						 *
+						 * @error fileuploader-uploading-data-failed
+						 */
+						return reject( new CKEditorError(
+							'fileuploader-uploading-data-failed: Uploading file failed.',
+							this,
+							{ message: xhrResponse.message }
+						) );
+					}
+
+					return reject( xhrResponse.error );
+				}
+
+				return resolve( xhrResponse );
+			} );
+
+			xhr.addEventListener( 'error', () => reject( new Error( 'Network Error' ) ) );
+			xhr.addEventListener( 'abort', () => reject( new Error( 'Abort' ) ) );
+
+			xhr.send( formData );
+		} );
+	}
+
+	/**
+	 * Fired when error occurs.
+	 *
+	 * @event error
+	 * @param {String} error Error message
+	 */
+
+	/**
+	 * Fired on upload progress.
+	 *
+	 * @event progress
+	 * @param {Object} status Total and uploaded status
+	 */
+}
+
+mix( FileUploader, EmitterMixin );
+
+/**
+ * Transforms Base64 string data into file.
+ *
+ * @param {String} base64 String data.
+ * @param {Number} [sliceSize=512]
+ * @returns {Blob}
+ * @private
+ */
+function _base64ToBlob( base64, sliceSize = 512 ) {
+	try {
+		const contentType = base64.match( BASE64_HEADER_REG_EXP )[ 1 ];
+		const base64Data = atob( base64.replace( BASE64_HEADER_REG_EXP, '' ) );
+
+		const byteArrays = [];
+
+		for ( let offset = 0; offset < base64Data.length; offset += sliceSize ) {
+			const slice = base64Data.slice( offset, offset + sliceSize );
+			const byteNumbers = new Array( slice.length );
+
+			for ( let i = 0; i < slice.length; i++ ) {
+				byteNumbers[ i ] = slice.charCodeAt( i );
+			}
+
+			byteArrays.push( new Uint8Array( byteNumbers ) );
+		}
+
+		return new Blob( byteArrays, { type: contentType } );
+	} catch ( error ) {
+		/**
+		 * Problem with decoding Base64 image data.
+		 *
+		 * @error fileuploader-decoding-image-data-error
+		 */
+		throw new CKEditorError( 'fileuploader-decoding-image-data-error: Problem with decoding Base64 image data.', null );
+	}
+}
+
+/**
+ * Checks that string is Base64.
+ *
+ * @param {String} string
+ * @returns {Boolean}
+ * @private
+ */
+function _isBase64( string ) {
+	if ( typeof string !== 'string' ) {
+		return false;
+	}
+
+	const match = string.match( BASE64_HEADER_REG_EXP );
+	return !!( match && match.length );
+}

+ 78 - 0
packages/ckeditor-cloud-services-core/src/uploadgateway/uploadgateway.js

@@ -0,0 +1,78 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/**
+ * @module cloud-services-core/uploadgateway/uploadgateway
+ */
+
+import FileUploader from './fileuploader';
+import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
+
+/**
+ * UploadGateway abstracts file uploads to CKEditor Cloud Services.
+ */
+export default class UploadGateway {
+	/**
+	 * Creates `UploadGateway` instance.
+	 *
+	 * @param {module:cloud-services-core/token~Token} token Token used for authentication.
+	 * @param {String} apiAddress API address.
+	 */
+	constructor( token, apiAddress ) {
+		if ( !token ) {
+			/**
+			 * Token must be provided.
+			 *
+			 * @error uploadgateway-missing-token
+			 */
+			throw new CKEditorError( 'uploadgateway-missing-token: Token must be provided.', null );
+		}
+
+		if ( !apiAddress ) {
+			/**
+			 * Api address must be provided.
+			 *
+			 * @error uploadgateway-missing-api-address
+			 */
+			throw new CKEditorError( 'uploadgateway-missing-api-address: Api address must be provided.', null );
+		}
+
+		/**
+		 * CKEditor Cloud Services access token.
+		 *
+		 * @type {module:cloud-services-core/token~Token}
+		 * @private
+		 */
+		this._token = token;
+
+		/**
+		 * CKEditor Cloud Services API address.
+		 *
+		 * @type {String}
+		 * @private
+		 */
+		this._apiAddress = apiAddress;
+	}
+
+	/**
+	 * Creates a {@link module:cloud-services-core/uploadgateway/fileuploader~FileUploader} instance that wraps
+	 * file upload process. The file is being sent at a time when the
+	 * {@link module:cloud-services-core/uploadgateway/fileuploader~FileUploader#send} method is called.
+	 *
+	 *     const token = await Token.create( 'https://token-endpoint' );
+	 *     new UploadGateway( token, 'https://example.org' )
+	 *        .upload( 'FILE' )
+	 *        .onProgress( ( data ) => console.log( data ) )
+	 *        .send()
+	 *        .then( ( response ) => console.log( response ) );
+	 *
+	 * @param {Blob|String} fileOrData A blob object or a data string encoded with Base64.
+	 * @returns {module:cloud-services-core/uploadgateway/fileuploader~FileUploader} Returns `FileUploader` instance.
+	 */
+	upload( fileOrData ) {
+		return new FileUploader( fileOrData, this._token, this._apiAddress );
+	}
+}
+

+ 263 - 0
packages/ckeditor-cloud-services-core/tests/token/token.js

@@ -0,0 +1,263 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/* eslint-env commonjs, browser */
+
+import Token from '../../src/token/token';
+import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
+
+describe( 'Token', () => {
+	let requests;
+
+	beforeEach( () => {
+		requests = [];
+
+		const xhr = sinon.useFakeXMLHttpRequest();
+
+		xhr.onCreate = request => {
+			requests.push( request );
+		};
+	} );
+
+	afterEach( () => {
+		sinon.restore();
+	} );
+
+	describe( 'constructor()', () => {
+		it( 'should throw error when no tokenUrl provided', () => {
+			expect( () => new Token() ).to.throw(
+				CKEditorError,
+				'token-missing-token-url'
+			);
+		} );
+
+		it( 'should set a init token value', () => {
+			const token = new Token( 'http://token-endpoint', { initValue: 'initValue', autoRefresh: false } );
+
+			expect( token.value ).to.equal( 'initValue' );
+		} );
+
+		it( 'should fire `change:value` event if the value of the token has changed', done => {
+			const token = new Token( 'http://token-endpoint', { autoRefresh: false } );
+
+			token.on( 'change:value', ( event, name, newValue ) => {
+				expect( newValue ).to.equal( 'token-value' );
+
+				done();
+			} );
+
+			token.init();
+
+			requests[ 0 ].respond( 200, '', 'token-value' );
+		} );
+
+		it( 'should accept the callback in the constructor', () => {
+			expect( () => {
+				// eslint-disable-next-line
+				const token = new Token( () => Promise.resolve( 'token' ) );
+			} ).to.not.throw();
+		} );
+	} );
+
+	describe( 'init()', () => {
+		it( 'should get a token value from endpoint', done => {
+			const token = new Token( 'http://token-endpoint', { autoRefresh: false } );
+
+			token.init()
+				.then( () => {
+					expect( token.value ).to.equal( 'token-value' );
+
+					done();
+				} );
+
+			requests[ 0 ].respond( 200, '', 'token-value' );
+		} );
+
+		it( 'should get a token from the refreshToken function when is provided', () => {
+			const token = new Token( () => Promise.resolve( 'token-value' ), { autoRefresh: false } );
+
+			return token.init()
+				.then( () => {
+					expect( token.value ).to.equal( 'token-value' );
+				} );
+		} );
+
+		it( 'should start token refresh every 1 hour', done => {
+			const clock = sinon.useFakeTimers( { toFake: [ 'setInterval' ] } );
+
+			const token = new Token( 'http://token-endpoint', { initValue: 'initValue' } );
+
+			token.init()
+				.then( () => {
+					clock.tick( 3600000 );
+					clock.tick( 3600000 );
+					clock.tick( 3600000 );
+					clock.tick( 3600000 );
+					clock.tick( 3600000 );
+
+					expect( requests.length ).to.equal( 5 );
+
+					clock.restore();
+
+					done();
+				} );
+		} );
+	} );
+
+	describe( 'destroy', () => {
+		it( 'should stop refreshing the token', () => {
+			const clock = sinon.useFakeTimers( { toFake: [ 'setInterval', 'clearInterval' ] } );
+			const token = new Token( 'http://token-endpoint', { initValue: 'initValue' } );
+
+			return token.init()
+				.then( () => {
+					clock.tick( 3600000 );
+					clock.tick( 3600000 );
+
+					expect( requests.length ).to.equal( 2 );
+
+					token.destroy();
+
+					clock.tick( 3600000 );
+					clock.tick( 3600000 );
+					clock.tick( 3600000 );
+
+					expect( requests.length ).to.equal( 2 );
+				} );
+		} );
+	} );
+
+	describe( 'refreshToken()', () => {
+		it( 'should get a token from the specified address', done => {
+			const token = new Token( 'http://token-endpoint', { initValue: 'initValue', autoRefresh: false } );
+
+			token.refreshToken()
+				.then( newToken => {
+					expect( newToken.value ).to.equal( 'token-value' );
+
+					done();
+				} );
+
+			requests[ 0 ].respond( 200, '', 'token-value' );
+		} );
+
+		it( 'should get a token from the specified callback function', () => {
+			const token = new Token( () => Promise.resolve( 'token-value' ), { initValue: 'initValue', autoRefresh: false } );
+
+			return token.refreshToken()
+				.then( newToken => {
+					expect( newToken.value ).to.equal( 'token-value' );
+				} );
+		} );
+
+		it( 'should throw an error when cannot download new token', () => {
+			const token = new Token( 'http://token-endpoint', { initValue: 'initValue', autoRefresh: false } );
+			const promise = token._refresh();
+
+			requests[ 0 ].respond( 401 );
+
+			return promise.then( () => {
+				throw new Error( 'Promise should be rejected' );
+			}, error => {
+				expect( error.constructor ).to.equal( CKEditorError );
+				expect( error ).to.match( /token-cannot-download-new-token/ );
+			} );
+		} );
+
+		it( 'should throw an error when the response is aborted', () => {
+			const token = new Token( 'http://token-endpoint', { initValue: 'initValue', autoRefresh: false } );
+			const promise = token._refresh();
+
+			requests[ 0 ].abort();
+
+			return promise.then( () => {
+				throw new Error( 'Promise should be rejected' );
+			}, error => {
+				expect( error ).to.match( /Abort/ );
+			} );
+		} );
+
+		it( 'should throw an error when network error occurs', () => {
+			const token = new Token( 'http://token-endpoint', { initValue: 'initValue', autoRefresh: false } );
+			const promise = token._refresh();
+
+			requests[ 0 ].error();
+
+			return promise.then( () => {
+				throw new Error( 'Promise should be rejected' );
+			}, error => {
+				expect( error ).to.match( /Network Error/ );
+			} );
+		} );
+
+		it( 'should throw an error when the callback throws error', () => {
+			const token = new Token( () => Promise.reject( 'Custom error occurred' ), { initValue: 'initValue', autoRefresh: false } );
+
+			token.refreshToken()
+				.catch( error => {
+					expect( error ).to.equal( 'Custom error occurred' );
+				} );
+		} );
+	} );
+
+	describe( '_startRefreshing()', () => {
+		it( 'should start refreshing', () => {
+			const clock = sinon.useFakeTimers( { toFake: [ 'setInterval' ] } );
+
+			const token = new Token( 'http://token-endpoint', { initValue: 'initValue', autoRefresh: false } );
+
+			token._startRefreshing();
+
+			clock.tick( 3600000 );
+			clock.tick( 3600000 );
+			clock.tick( 3600000 );
+			clock.tick( 3600000 );
+			clock.tick( 3600000 );
+
+			expect( requests.length ).to.equal( 5 );
+
+			clock.restore();
+		} );
+	} );
+
+	describe( '_stopRefreshing()', () => {
+		it( 'should stop refreshing', done => {
+			const clock = sinon.useFakeTimers( { toFake: [ 'setInterval', 'clearInterval' ] } );
+
+			const token = new Token( 'http://token-endpoint', { initValue: 'initValue' } );
+
+			token.init()
+				.then( () => {
+					clock.tick( 3600000 );
+					clock.tick( 3600000 );
+					clock.tick( 3600000 );
+
+					token._stopRefreshing();
+
+					clock.tick( 3600000 );
+					clock.tick( 3600000 );
+
+					expect( requests.length ).to.equal( 3 );
+
+					clock.restore();
+
+					done();
+				} );
+		} );
+	} );
+
+	describe( 'static create()', () => {
+		it( 'should return a initialized token', done => {
+			Token.create( 'http://token-endpoint', { autoRefresh: false } )
+				.then( token => {
+					expect( token.value ).to.equal( 'token-value' );
+
+					done();
+				} );
+
+			requests[ 0 ].respond( 200, '', 'token-value' );
+		} );
+	} );
+} );

+ 223 - 0
packages/ckeditor-cloud-services-core/tests/uploadgateway/fileuploader.js

@@ -0,0 +1,223 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/* eslint-env commonjs, browser */
+
+import FileUploader from '../../src/uploadgateway/fileuploader';
+import Token from '../../src/token/token';
+import CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';
+
+const API_ADDRESS = 'https://example.dev';
+const BASE_64_FILE = 'data:image/gif;base64,R0lGODlhCQAJAPIAAGFhYZXK/1FRUf///' +
+	'9ra2gD/AAAAAAAAACH5BAEAAAUALAAAAAAJAAkAAAMYWFqwru2xERcYJLSNNWNBVimC5wjfaTkJADs=';
+
+describe( 'FileUploader', () => {
+	const token = new Token( 'url', { initValue: 'token', autoRefresh: false } );
+
+	let fileUploader;
+
+	beforeEach( () => {
+		fileUploader = new FileUploader( BASE_64_FILE, token, API_ADDRESS );
+	} );
+
+	describe( 'constructor()', () => {
+		it( 'should throw error when no fileOrData provided', () => {
+			expect( () => new FileUploader() ).to.throw( CKEditorError, 'fileuploader-missing-file' );
+		} );
+
+		it( 'should throw error when no token provided', () => {
+			expect( () => new FileUploader( 'file' ) ).to.throw( CKEditorError, 'fileuploader-missing-token' );
+		} );
+
+		it( 'should throw error when no api address provided', () => {
+			expect( () => new FileUploader( 'file', token ) ).to.throw( CKEditorError, 'fileuploader-missing-api-address' );
+		} );
+
+		it( 'should throw error when wrong Base64 file is provided', () => {
+			expect( () => new FileUploader( 'data:image/gif;base64,R', token, API_ADDRESS ) )
+				.to.throw( CKEditorError, 'fileuploader-decoding-image-data-error' );
+		} );
+
+		it( 'should convert base64 to file', done => {
+			const fileReader = new FileReader();
+
+			fileReader.readAsDataURL( fileUploader.file );
+			fileReader.onloadend = () => {
+				expect( fileReader.result ).to.equal( BASE_64_FILE );
+
+				done();
+			};
+		} );
+
+		it( 'should set `file` field', () => {
+			const file = new File( [], 'test.jpg' );
+
+			const fileUploader = new FileUploader( file, token, API_ADDRESS );
+
+			expect( fileUploader.file.name ).to.equal( 'test.jpg' );
+		} );
+	} );
+
+	describe( 'onProgress()', () => {
+		it( 'should register callback for `progress` event', done => {
+			fileUploader.onProgress( data => {
+				expect( data ).to.be.deep.equal( { total: 12345, loaded: 123 } );
+				done();
+			} );
+
+			fileUploader.fire( 'progress', { total: 12345, loaded: 123 } );
+		} );
+	} );
+
+	describe( 'onError()', () => {
+		it( 'should register callback for `error` event', done => {
+			fileUploader.onError( data => {
+				expect( data ).to.be.instanceOf( Error );
+				expect( data.message ).to.equal( 'TEST' );
+
+				done();
+			} );
+
+			fileUploader.fire( 'error', new Error( 'TEST' ) );
+		} );
+
+		it( 'should call registered callback for `error` event once', () => {
+			const spy = sinon.spy();
+			fileUploader.onError( spy );
+
+			fileUploader.fire( 'error', new Error( 'TEST' ) );
+			fileUploader.fire( 'error', new Error( 'TEST' ) );
+
+			sinon.assert.calledOnce( spy );
+		} );
+	} );
+
+	describe( 'send()', () => {
+		let request;
+
+		beforeEach( () => {
+			const xhr = sinon.useFakeXMLHttpRequest();
+
+			xhr.onCreate = r => {
+				request = r;
+			};
+		} );
+
+		afterEach( () => {
+			sinon.restore();
+		} );
+
+		it( 'should sent request with correct data (url, method, type, headers)', done => {
+			fileUploader
+				.send()
+				.then( () => {
+					expect( request.url ).to.equal( API_ADDRESS );
+					expect( request.method ).to.equal( 'POST' );
+					expect( request.responseType ).to.equal( 'json' );
+					expect( request.requestHeaders ).to.be.deep.equal( { Authorization: 'token' } );
+
+					done();
+				} );
+
+			request.respond( 200, { 'Content-Type': 'application/json' },
+				JSON.stringify( { 'default': 'https://test.dev' } )
+			);
+		} );
+
+		it( 'should fire `error` event with error message when response is failed', done => {
+			fileUploader
+				.onError( error => {
+					expect( error ).to.equal( 'Message' );
+
+					done();
+				} )
+				.send();
+
+			request.respond( 400, { 'Content-Type': 'application/json' },
+				JSON.stringify( {
+					error: 'Error',
+					message: 'Message'
+				} )
+			);
+		} );
+
+		it( 'should fire `error` event with error when response is failed', done => {
+			fileUploader
+				.onError( error => {
+					expect( error ).to.equal( 'Error' );
+
+					done();
+				} )
+				.send();
+
+			request.respond( 400, { 'Content-Type': 'application/json' },
+				JSON.stringify( {
+					error: 'Error'
+				} )
+			);
+		} );
+
+		it( 'should fire `error` event when response is aborted', done => {
+			fileUploader
+				.onError( error => {
+					expect( error ).to.equal( 'Abort' );
+
+					done();
+				} )
+				.send();
+
+			request.abort();
+		} );
+
+		it( 'should fire `error` event when network error occurs', done => {
+			fileUploader
+				.onError( error => {
+					expect( error ).to.equal( 'Network Error' );
+
+					done();
+				} )
+				.send();
+
+			request.error();
+		} );
+
+		it( 'should fire `progress` event', done => {
+			fileUploader
+				.onProgress( data => {
+					expect( data.total ).to.equal( 1 );
+					expect( data.uploaded ).to.equal( 10 );
+
+					done();
+				} )
+				.send();
+
+			request.uploadProgress( { total: 1, loaded: 10 } );
+			request.respond( 200 );
+		} );
+	} );
+
+	describe( 'abort()', () => {
+		let request;
+
+		beforeEach( () => {
+			const xhr = sinon.useFakeXMLHttpRequest();
+
+			xhr.onCreate = r => {
+				request = r;
+			};
+		} );
+
+		afterEach( () => {
+			sinon.restore();
+		} );
+
+		it( 'should abort xhr request', () => {
+			fileUploader.send();
+			fileUploader.abort();
+
+			expect( request.aborted ).to.be.true;
+		} );
+	} );
+} );

+ 31 - 0
packages/ckeditor-cloud-services-core/tests/uploadgateway/uploadgateway.js

@@ -0,0 +1,31 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+import FileUploader from '../../src/uploadgateway/fileuploader';
+import UploadGateway from '../../src/uploadgateway/uploadgateway';
+import Token from '../../src/token/token';
+import { expectToThrowCKEditorError } from '@ckeditor/ckeditor5-utils/tests/_utils/utils';
+
+describe( 'UploadGateway', () => {
+	const token = new Token( 'url', { initValue: 'token', autoRefresh: false } );
+
+	describe( 'constructor()', () => {
+		it( 'should throw error when no token provided', () => {
+			expectToThrowCKEditorError( () => new UploadGateway( undefined, 'test' ), 'uploadgateway-missing-token' );
+		} );
+
+		it( 'should throw error when no apiAddress provided', () => {
+			expectToThrowCKEditorError( () => new UploadGateway( token ), 'uploadgateway-missing-api-address' );
+		} );
+	} );
+
+	describe( 'upload()', () => {
+		it( 'should return `FileUploader` instance', () => {
+			const uploader = new UploadGateway( token, 'test' );
+
+			expect( uploader.upload( 'file' ) ).to.be.instanceOf( FileUploader );
+		} );
+	} );
+} );

+ 16 - 0
packages/ckeditor5-adapter-ckfinder/.editorconfig

@@ -0,0 +1,16 @@
+# Configurations to normalize the IDE behavior.
+# http://editorconfig.org/
+
+root = true
+
+[*]
+indent_style = tab
+tab_width = 4
+charset = utf-8
+end_of_line = lf
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[package.json]
+indent_style = space
+tab_width = 2

+ 12 - 0
packages/ckeditor5-adapter-ckfinder/.eslintrc.js

@@ -0,0 +1,12 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/* eslint-env node */
+
+'use strict';
+
+module.exports = {
+	extends: 'ckeditor5'
+};

+ 18 - 0
packages/ckeditor5-adapter-ckfinder/.gitattributes

@@ -0,0 +1,18 @@
+*			text=auto
+
+*.htaccess	eol=lf
+*.cgi		eol=lf
+*.sh		eol=lf
+
+*.css		text
+*.htm		text
+*.html		text
+*.js		text
+*.json		text
+*.php		text
+*.txt		text
+*.md		text
+
+*.png		-text
+*.gif		-text
+*.jpg		-text

+ 9 - 0
packages/ckeditor5-adapter-ckfinder/.github/PULL_REQUEST_TEMPLATE.md

@@ -0,0 +1,9 @@
+### Suggested merge commit message ([convention](https://github.com/ckeditor/ckeditor5-design/wiki/Git-commit-message-convention))
+
+Type: Message. Closes ckeditor/ckeditor5#000.
+
+---
+
+### Additional information
+
+*For example – encountered issues, assumptions you had to make, other affected tickets, etc.*

+ 1 - 0
packages/ckeditor5-adapter-ckfinder/.gitignore

@@ -0,0 +1 @@
+node_modules/

+ 3 - 0
packages/ckeditor5-adapter-ckfinder/.stylelintrc

@@ -0,0 +1,3 @@
+{
+	"extends": "stylelint-config-ckeditor5"
+}

+ 31 - 0
packages/ckeditor5-adapter-ckfinder/.travis.yml

@@ -0,0 +1,31 @@
+sudo: required
+dist: xenial
+addons:
+  chrome: stable
+  firefox: latest
+language: node_js
+services:
+- xvfb
+node_js:
+- '10'
+cache:
+  yarn: true
+branches:
+  except:
+  - stable
+before_install:
+- export START_TIME=$( date +%s )
+- npm i -g yarn
+install:
+- yarn add @ckeditor/ckeditor5-dev-tests
+- ckeditor5-dev-tests-install-dependencies
+script:
+- ckeditor5-dev-tests-travis
+after_script:
+- export END_TIME=$( date +%s )
+- ckeditor5-dev-tests-notify-travis-status
+after_success:
+- ckeditor5-dev-tests-save-revision
+env:
+  global:
+  - secure: SqWhdljqCUz3qhunI+Ji1JHMRqGfpJFlgaOVn8dWF7/ugmwaZM+TYzozdRKq6O1z+UsVzxfX2AC7AItTmfx/7vb1XbqtJfIym3XnJ/GL4hf1N3MC1Xuyr6AWTH+fjNs5ceCWilivkBqUKEiSdBwt3/GC4nOsL9kcCBepAkC6C4a37KcM6l5UQhzZ/VYW38Msp/7njhMaAP1jrvf97AXVkbGS9I/0h7lvvneg4wrepa95YguQew+263HOU37IKHpWRm4iU8QIQlKzL3LzeE8IN7oOMPK5GEdUFzu8XbRQM0qncdQSSFJjo4r0/Eyiy0RaWUbHtfg5cHaeZ0UV5Xocm801QW0gepJuM65NX/GqmKFrcuvLsYkPtHy9C0mIN+JYpsx/o9P+l+eS8O1cXcLUWJ9ttx2ODz4wsvHehJ809PIFDh2LqBFdore2Gd4z3X7nbL6COnFmCWVMQ36Xx16hTjwEzmJO2YKH/BPei4U73OBHXorljwu0omypq0iYnY8bEPd4cCk1TQOadlsGaAI47MYOIh259rxK3ZTmgBgPv1/sTvYTiq+7JokO+9+MwLsTG+BxAgQckwN8C4kUnCqlRswiyRcfoOdhuc62SwazGLDE6cNGRFzAFUhY/UxqzA6jdxqxXGYXPfHn/FNKpkBdozURk4sacq5x7PEsB8boYmw=

+ 157 - 0
packages/ckeditor5-adapter-ckfinder/CHANGELOG.md

@@ -0,0 +1,157 @@
+Changelog
+=========
+
+## [19.0.0](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v18.0.0...v19.0.0) (2020-04-29)
+
+Internal changes only (updated dependencies, documentation, etc.).
+
+
+## [18.0.0](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v17.0.0...v18.0.0) (2020-03-19)
+
+Internal changes only (updated dependencies, documentation, etc.).
+
+
+## [17.0.0](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v16.0.0...v17.0.0) (2020-02-18)
+
+### Other changes
+
+* Updated translations. ([b3bc679](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/b3bc679))
+
+
+## [16.0.0](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v15.0.0...v16.0.0) (2019-12-04)
+
+### Other changes
+
+* Updated translations. ([5249150](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/5249150))
+
+
+## [15.0.0](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v11.0.5...v15.0.0) (2019-10-23)
+
+### Other changes
+
+* Updated translations. ([b7ae885](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/b7ae885)) ([f03c652](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/f03c652))
+
+
+## [11.0.5](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v11.0.4...v11.0.5) (2019-08-26)
+
+### Other changes
+
+* Changed the URL under bugs key in package.json file. Now we have one issue tracker. See [ckeditor/ckeditor5#1988](https://github.com/ckeditor/ckeditor5/issues/1988). ([7edd73b](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/7edd73b))
+* Updated translations. ([8fb4cc2](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/8fb4cc2))
+
+
+## [11.0.4](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v11.0.3...v11.0.4) (2019-07-10)
+
+Internal changes only (updated dependencies, documentation, etc.).
+
+
+## [11.0.3](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v11.0.2...v11.0.3) (2019-07-04)
+
+Internal changes only (updated dependencies, documentation, etc.).
+
+
+## [11.0.2](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v11.0.1...v11.0.2) (2019-06-05)
+
+### Other changes
+
+* Updated translations. ([7d00af1](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/7d00af1))
+
+
+## [11.0.1](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v11.0.0...v11.0.1) (2019-04-10)
+
+### Other changes
+
+* Updated translations. ([3a0fe51](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/3a0fe51))
+
+
+## [11.0.0](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v10.0.4...v11.0.0) (2019-02-28)
+
+### Other changes
+
+* Updated translations. ([0e55853](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/0e55853)) ([818eeae](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/818eeae)) ([707fa21](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/707fa21))
+
+### BREAKING CHANGES
+
+* Upgraded minimal versions of Node to `8.0.0` and npm to `5.7.1`. See: [ckeditor/ckeditor5#1507](https://github.com/ckeditor/ckeditor5/issues/1507). ([612ea3c](https://github.com/ckeditor/ckeditor5-cloud-services/commit/612ea3c))
+
+
+## [10.0.4](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v10.0.3...v10.0.4) (2018-12-05)
+
+Internal changes only (updated dependencies, documentation, etc.).
+
+
+## [10.0.3](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v10.0.2...v10.0.3) (2018-10-08)
+
+### Other changes
+
+* Updated translations. ([896412d](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/896412d))
+
+
+## [10.0.2](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v10.0.1...v10.0.2) (2018-07-18)
+
+### Other changes
+
+* Updated translations. ([69db8e3](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/69db8e3))
+
+
+## [10.0.1](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v10.0.0...v10.0.1) (2018-06-21)
+
+### Other changes
+
+* Updated translations. ([6360b78](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/6360b78))
+
+
+## [10.0.0](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v1.0.0-beta.4...v10.0.0) (2018-04-25)
+
+### Other changes
+
+* Changed the license to GPL2+ only. See [ckeditor/ckeditor5#991](https://github.com/ckeditor/ckeditor5/issues/991). ([06caac5](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/06caac5))
+
+### BREAKING CHANGES
+
+* The license under which CKEditor 5 is released has been changed from a triple GPL, LGPL and MPL license to a GPL2+ only. See [ckeditor/ckeditor5#991](https://github.com/ckeditor/ckeditor5/issues/991) for more information.
+
+
+## [1.0.0-beta.4](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v1.0.0-beta.2...v1.0.0-beta.4) (2018-04-19)
+
+### Other changes
+
+* Updated translations. ([02712bb](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/02712bb))
+
+
+## [1.0.0-beta.2](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v1.0.0-beta.1...v1.0.0-beta.2) (2018-04-10)
+
+Internal changes only (updated dependencies, documentation, etc.).
+
+
+## [1.0.0-beta.1](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v1.0.0-alpha.2...v1.0.0-beta.1) (2018-03-15)
+
+Internal changes only (updated dependencies, documentation, etc.).
+
+
+## [1.0.0-alpha.2](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v1.0.0-alpha.1...v1.0.0-alpha.2) (2017-11-14)
+
+### Other changes
+
+* Updated translations. ([7f80868](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/7f80868))
+
+
+## [1.0.0-alpha.1](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v0.1.1...v1.0.0-alpha.1) (2017-10-03)
+
+### Other changes
+
+* The plugin will not log a warning when `config.ckfinder.uploadUrl` is not specified (because `FileRepository` will do it itself). Closes [#5](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/issues/5). ([1a15688](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/1a15688))
+
+
+## [0.1.1](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/compare/v0.1.0...v0.1.1) (2017-09-03)
+
+### Other changes
+
+* Aligned the implementation to changes in the image upload. ([eb456ac](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/commit/eb456ac))
+
+
+## 0.1.0 (2017-05-08)
+
+### Features
+
+* Initial implementation. Closes [#1](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/issues/1).

+ 4 - 0
packages/ckeditor5-adapter-ckfinder/CONTRIBUTING.md

@@ -0,0 +1,4 @@
+Contributing
+========================================
+
+See the [official contributors' guide to CKEditor 5](https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html) to learn more.

+ 17 - 0
packages/ckeditor5-adapter-ckfinder/LICENSE.md

@@ -0,0 +1,17 @@
+Software License Agreement
+==========================
+
+**CKFinder adapter for CKEditor 5** – https://github.com/ckeditor/ckeditor5-adapter-ckfinder <br>
+Copyright (c) 2003-2020, [CKSource](http://cksource.com) Frederico Knabben. All rights reserved.
+
+Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html).
+
+Sources of Intellectual Property Included in CKEditor
+-----------------------------------------------------
+
+Where not otherwise indicated, all CKEditor content is authored by CKSource engineers and consists of CKSource-owned intellectual property. In some specific instances, CKEditor will incorporate work done by developers outside of CKSource with their express permission.
+
+Trademarks
+----------
+
+**CKEditor** is a trademark of [CKSource](http://cksource.com) Frederico Knabben. All other brand and product names are trademarks, registered trademarks or service marks of their respective holders.

+ 18 - 0
packages/ckeditor5-adapter-ckfinder/README.md

@@ -0,0 +1,18 @@
+CKFinder adapter for CKEditor 5
+========================================
+
+[![npm version](https://badge.fury.io/js/%40ckeditor%2Fckeditor5-adapter-ckfinder.svg)](https://www.npmjs.com/package/@ckeditor/ckeditor5-adapter-ckfinder)
+[![Dependency Status](https://david-dm.org/ckeditor/ckeditor5-adapter-ckfinder/status.svg)](https://david-dm.org/ckeditor/ckeditor5-adapter-ckfinder)
+[![devDependency Status](https://david-dm.org/ckeditor/ckeditor5-adapter-ckfinder/dev-status.svg)](https://david-dm.org/ckeditor/ckeditor5-adapter-ckfinder?type=dev)
+
+This package implements a CKEditor 5 upload adapter compatible with the [CKFinder file manager and uploader](https://ckeditor.com/ckfinder/)'s server–side connector.
+
+## Documentation
+
+See the ["CKFinder integration" guide](https://ckeditor.com/docs/ckeditor5/latest/features/ckfinder.html) and the [plugin documentation](https://ckeditor.com/docs/ckeditor5/latest/api/adapter-ckfinder.html) to learn how to configure the adapter.
+
+Check out the {@link features/image-upload/image-upload comprehensive "Image upload overview"} to learn about other ways to upload images into CKEditor 5.
+
+## License
+
+Licensed under the terms of [GNU General Public License Version 2 or later](http://www.gnu.org/licenses/gpl.html). For full details about the license, please check the `LICENSE.md` file or [https://ckeditor.com/legal/ckeditor-oss-license](https://ckeditor.com/legal/ckeditor-oss-license).

+ 32 - 0
packages/ckeditor5-adapter-ckfinder/docs/api/adapter-ckfinder.md

@@ -0,0 +1,32 @@
+---
+category: api-reference
+---
+
+# CKFinder adapter for CKEditor 5
+
+[![npm version](https://badge.fury.io/js/%40ckeditor%2Fckeditor5-adapter-ckfinder.svg)](https://www.npmjs.com/package/@ckeditor/ckeditor5-adapter-ckfinder)
+
+This package implements a CKEditor 5 upload adapter compatible with the [CKFinder file manager and uploader](https://ckeditor.com/ckfinder/)'s server–side connector.
+
+## Documentation
+
+See the {@link features/ckfinder "CKFinder integration" guide} and the {@link module:adapter-ckfinder/uploadadapter~CKFinderUploadAdapter plugin documentation} to learn how to configure the adapter.
+
+Check out the {@link features/image-upload comprehensive "Image upload" guide} to learn about other ways to upload images into CKEditor 5.
+
+## Installation
+
+```bash
+npm install --save @ckeditor/ckeditor5-adapter-ckfinder
+```
+
+## Contribute
+
+The source code of this package is available on GitHub in https://github.com/ckeditor/ckeditor5/tree/master/packages/ckeditor5-adapter-ckfinder.
+
+## External links
+
+* [`@ckeditor/ckeditor5-adapter-ckfinder` on npm](https://www.npmjs.com/package/@ckeditor/ckeditor5-adapter-ckfinder)
+* [`ckeditor/ckeditor5-adapter-ckfinder` on GitHub](https://github.com/ckeditor/ckeditor5/tree/master/packages/ckeditor5-adapter-ckfinder)
+* [Issue tracker](https://github.com/ckeditor/ckeditor5/issues)
+* [Changelog](https://github.com/ckeditor/ckeditor5-adapter-ckfinder/blob/master/CHANGELOG.md)

+ 3 - 0
packages/ckeditor5-adapter-ckfinder/lang/contexts.json

@@ -0,0 +1,3 @@
+{
+	"Cannot upload file:": "A generic error message displayed on upload failure. The file name is concatenated to this text."
+}

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/af.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Afrikaans (https://www.transifex.com/ckeditor/teams/11143/af/)\n"
+"Language: af\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Lêer nie opgelaai nie:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/ar.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Arabic (https://www.transifex.com/ckeditor/teams/11143/ar/)\n"
+"Language: ar\n"
+"Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "لا يمكن رفع الملف:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/az.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Azerbaijani (https://www.transifex.com/ckeditor/teams/11143/az/)\n"
+"Language: az\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Fayl yüklənə bilmir"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/ca.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Catalan (https://www.transifex.com/ckeditor/teams/11143/ca/)\n"
+"Language: ca\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "No es pot pujar l'arxiu:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/cs.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Czech (https://www.transifex.com/ckeditor/teams/11143/cs/)\n"
+"Language: cs\n"
+"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Soubor nelze nahrát:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/da.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Danish (https://www.transifex.com/ckeditor/teams/11143/da/)\n"
+"Language: da\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Kan ikke uploade fil:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/de-ch.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: German (Switzerland) (https://www.transifex.com/ckeditor/teams/11143/de_CH/)\n"
+"Language: de_CH\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Datei kann nicht hochgeladen werden:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/de.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: German (https://www.transifex.com/ckeditor/teams/11143/de/)\n"
+"Language: de\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Datei kann nicht hochgeladen werden:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/en-au.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: English (Australia) (https://www.transifex.com/ckeditor/teams/11143/en_AU/)\n"
+"Language: en_AU\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Cannot upload file:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/en-gb.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: English (United Kingdom) (https://www.transifex.com/ckeditor/teams/11143/en_GB/)\n"
+"Language: en_GB\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Cannot upload file:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/en.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language: \n"
+"Language-Team: \n"
+"Plural-Forms: \n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Cannot upload file:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/es.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Spanish (https://www.transifex.com/ckeditor/teams/11143/es/)\n"
+"Language: es\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "No se pudo cargar el archivo:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/et.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Estonian (https://www.transifex.com/ckeditor/teams/11143/et/)\n"
+"Language: et\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Faili ei suudeta üles laadida:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/eu.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Basque (https://www.transifex.com/ckeditor/teams/11143/eu/)\n"
+"Language: eu\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Ezin da fitxategia kargatu:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/fa.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Persian (https://www.transifex.com/ckeditor/teams/11143/fa/)\n"
+"Language: fa\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "فایل آپلود نمی‌شود:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/fi.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Finnish (https://www.transifex.com/ckeditor/teams/11143/fi/)\n"
+"Language: fi\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Tiedostoa ei voitu ladata:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/fr.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: French (https://www.transifex.com/ckeditor/teams/11143/fr/)\n"
+"Language: fr\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Envoi du fichier échoué :"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/gl.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Galician (https://www.transifex.com/ckeditor/teams/11143/gl/)\n"
+"Language: gl\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Non é posíbel cargar o ficheiro:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/gu.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Gujarati (https://www.transifex.com/ckeditor/teams/11143/gu/)\n"
+"Language: gu\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "ફાઇલ અપલોડ ન થઇ શકી"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/he.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Hebrew (https://www.transifex.com/ckeditor/teams/11143/he/)\n"
+"Language: he\n"
+"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n == 2 && n % 1 == 0) ? 1: (n % 10 == 0 && n % 1 == 0 && n > 10) ? 2 : 3;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "לא ניתן להעלות את הקובץ הבא:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/hr.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Croatian (https://www.transifex.com/ckeditor/teams/11143/hr/)\n"
+"Language: hr\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Datoteku nije moguće poslati:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/hu.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Hungarian (https://www.transifex.com/ckeditor/teams/11143/hu/)\n"
+"Language: hu\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Nem sikerült a fájl feltöltése:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/id.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Indonesian (https://www.transifex.com/ckeditor/teams/11143/id/)\n"
+"Language: id\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Tidak dapat mengunggah berkas:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/it.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Italian (https://www.transifex.com/ckeditor/teams/11143/it/)\n"
+"Language: it\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Impossibile caricare il file:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/ja.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Japanese (https://www.transifex.com/ckeditor/teams/11143/ja/)\n"
+"Language: ja\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "ファイルをアップロードできません:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/km.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Khmer (https://www.transifex.com/ckeditor/teams/11143/km/)\n"
+"Language: km\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "មិនអាច​អាប់ឡូត​ឯកសារ៖"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/ko.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Korean (https://www.transifex.com/ckeditor/teams/11143/ko/)\n"
+"Language: ko\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "파일 업로드 불가"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/ku.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Kurdish (https://www.transifex.com/ckeditor/teams/11143/ku/)\n"
+"Language: ku\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "پەڕگەکە ناتوانرێت باربکرێت:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/lt.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Lithuanian (https://www.transifex.com/ckeditor/teams/11143/lt/)\n"
+"Language: lt\n"
+"Plural-Forms: nplurals=4; plural=(n % 10 == 1 && (n % 100 > 19 || n % 100 < 11) ? 0 : (n % 10 >= 2 && n % 10 <=9) && (n % 100 > 19 || n % 100 < 11) ? 1 : n % 1 != 0 ? 2: 3);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Negalima įkelti failo:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/lv.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Latvian (https://www.transifex.com/ckeditor/teams/11143/lv/)\n"
+"Language: lv\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Nevar augšupielādēt failu:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/ms.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Malay (https://www.transifex.com/ckeditor/teams/11143/ms/)\n"
+"Language: ms\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Gagal memuat naik fail"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/nb.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Norwegian Bokmål (https://www.transifex.com/ckeditor/teams/11143/nb/)\n"
+"Language: nb\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Kan ikke laste opp fil:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/ne.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Nepali (Nepal) (https://www.transifex.com/ckeditor/teams/11143/ne_NP/)\n"
+"Language: ne_NP\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "फाइल अपलोड गर्न मिल्दैन"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/nl.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Dutch (https://www.transifex.com/ckeditor/teams/11143/nl/)\n"
+"Language: nl\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Kan bestand niet uploaden:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/no.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Norwegian (https://www.transifex.com/ckeditor/teams/11143/no/)\n"
+"Language: no\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Kan ikke laste opp fil:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/pl.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Polish (https://www.transifex.com/ckeditor/teams/11143/pl/)\n"
+"Language: pl\n"
+"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Nie można przesłać pliku:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/pt-br.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Portuguese (Brazil) (https://www.transifex.com/ckeditor/teams/11143/pt_BR/)\n"
+"Language: pt_BR\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Não foi possível enviar o arquivo:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/pt.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Portuguese (https://www.transifex.com/ckeditor/teams/11143/pt/)\n"
+"Language: pt\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Não foi possível carregar o ficheiro:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/ro.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Romanian (https://www.transifex.com/ckeditor/teams/11143/ro/)\n"
+"Language: ro\n"
+"Plural-Forms: nplurals=3; plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Nu se poate încărca fișierul:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/ru.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Russian (https://www.transifex.com/ckeditor/teams/11143/ru/)\n"
+"Language: ru\n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Невозможно загрузить файл"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/si.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Sinhala (Sri Lanka) (https://www.transifex.com/ckeditor/teams/11143/si_LK/)\n"
+"Language: si_LK\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "ගොනුව යාවත්කාලීන කළ නොහැක:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/sk.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Slovak (https://www.transifex.com/ckeditor/teams/11143/sk/)\n"
+"Language: sk\n"
+"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n == 1 ? 0 : n % 1 == 0 && n >= 2 && n <= 4 ? 1 : n % 1 != 0 ? 2: 3);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Nie je možné nahrať súbor:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/sl.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Slovenian (https://www.transifex.com/ckeditor/teams/11143/sl/)\n"
+"Language: sl\n"
+"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Ni možno naložiti datoteke:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/sq.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Albanian (https://www.transifex.com/ckeditor/teams/11143/sq/)\n"
+"Language: sq\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Nuk mund të ngarkojë skedën:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/sr-latn.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Serbian (Latin) (https://www.transifex.com/ckeditor/teams/11143/sr@latin/)\n"
+"Language: sr@latin\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Postavljanje fajla je neuspešno:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/sr.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Serbian (https://www.transifex.com/ckeditor/teams/11143/sr/)\n"
+"Language: sr\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Постављање фајла је неуспешно:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/sv.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Swedish (https://www.transifex.com/ckeditor/teams/11143/sv/)\n"
+"Language: sv\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Kan inte ladda upp fil:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/th.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Thai (https://www.transifex.com/ckeditor/teams/11143/th/)\n"
+"Language: th\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "ไม่สามารถอัปโหลดไฟล์ได้:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/tr.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Turkish (https://www.transifex.com/ckeditor/teams/11143/tr/)\n"
+"Language: tr\n"
+"Plural-Forms: nplurals=2; plural=(n > 1);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Dosya yüklenemedi:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/ug.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Uighur (https://www.transifex.com/ckeditor/teams/11143/ug/)\n"
+"Language: ug\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "چىقىرىشقا بولمايدىغان ھۆججەت :"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/uk.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Ukrainian (https://www.transifex.com/ckeditor/teams/11143/uk/)\n"
+"Language: uk\n"
+"Plural-Forms: nplurals=4; plural=(n % 1 == 0 && n % 10 == 1 && n % 100 != 11 ? 0 : n % 1 == 0 && n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14) ? 1 : n % 1 == 0 && (n % 10 ==0 || (n % 10 >=5 && n % 10 <=9) || (n % 100 >=11 && n % 100 <=14 )) ? 2: 3);\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Неможливо завантажити файл:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/vi.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Vietnamese (https://www.transifex.com/ckeditor/teams/11143/vi/)\n"
+"Language: vi\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "Không thể tải file:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/zh-cn.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Chinese (China) (https://www.transifex.com/ckeditor/teams/11143/zh_CN/)\n"
+"Language: zh_CN\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "无法上传的文件:"

+ 21 - 0
packages/ckeditor5-adapter-ckfinder/lang/translations/zh.po

@@ -0,0 +1,21 @@
+# Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+#
+#                                     !!! IMPORTANT !!!
+#
+#         Before you edit this file, please keep in mind that contributing to the project
+#                translations is possible ONLY via the Transifex online service.
+#
+#         To submit your translations, visit https://www.transifex.com/ckeditor/ckeditor5.
+#
+#                   To learn more, check out the official contributor's guide:
+#     https://ckeditor.com/docs/ckeditor5/latest/framework/guides/contributing/contributing.html
+#
+msgid ""
+msgstr ""
+"Language-Team: Chinese (Taiwan) (https://www.transifex.com/ckeditor/teams/11143/zh_TW/)\n"
+"Language: zh_TW\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+msgctxt "A generic error message displayed on upload failure. The file name is concatenated to this text."
+msgid "Cannot upload file:"
+msgstr "無法上傳檔案:"

+ 72 - 0
packages/ckeditor5-adapter-ckfinder/package.json

@@ -0,0 +1,72 @@
+{
+  "name": "@ckeditor/ckeditor5-adapter-ckfinder",
+  "version": "19.0.0",
+  "description": "CKFinder adapter for CKEditor 5.",
+  "keywords": [
+    "ckeditor",
+    "ckeditor5",
+    "ckeditor 5",
+    "ckeditor5-feature",
+    "ckeditor5-plugin"
+  ],
+  "dependencies": {
+    "@ckeditor/ckeditor5-core": "^19.0.0",
+    "@ckeditor/ckeditor5-upload": "^19.0.0"
+  },
+  "devDependencies": {
+    "@ckeditor/ckeditor5-basic-styles": "^19.0.0",
+    "@ckeditor/ckeditor5-clipboard": "^19.0.0",
+    "@ckeditor/ckeditor5-editor-classic": "^19.0.0",
+    "@ckeditor/ckeditor5-enter": "^19.0.0",
+    "@ckeditor/ckeditor5-heading": "^19.0.0",
+    "@ckeditor/ckeditor5-image": "^19.0.0",
+    "@ckeditor/ckeditor5-list": "^19.0.0",
+    "@ckeditor/ckeditor5-paragraph": "^19.0.0",
+    "@ckeditor/ckeditor5-typing": "^19.0.0",
+    "@ckeditor/ckeditor5-undo": "^19.0.0",
+    "eslint": "^5.5.0",
+    "eslint-config-ckeditor5": "^2.0.0",
+    "husky": "^1.3.1",
+    "lint-staged": "^7.0.0",
+    "stylelint": "^11.1.1",
+    "stylelint-config-ckeditor5": "^1.0.0"
+  },
+  "engines": {
+    "node": ">=8.0.0",
+    "npm": ">=5.7.1"
+  },
+  "author": "CKSource (http://cksource.com/)",
+  "license": "GPL-2.0-or-later",
+  "homepage": "https://ckeditor.com/ckeditor-5",
+  "bugs": "https://github.com/ckeditor/ckeditor5/issues",
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/ckeditor/ckeditor5-adapter-ckfinder.git"
+  },
+  "files": [
+    "lang",
+    "src",
+    "theme"
+  ],
+  "scripts": {
+    "lint": "eslint --quiet '**/*.js'",
+    "stylelint": "stylelint --quiet --allow-empty-input 'theme/**/*.css' 'docs/**/*.css'"
+  },
+  "lint-staged": {
+    "**/*.js": [
+      "eslint --quiet"
+    ],
+    "**/*.css": [
+      "stylelint --quiet --allow-empty-input"
+    ]
+  },
+  "eslintIgnore": [
+    "src/lib/**",
+    "packages/**"
+  ],
+  "husky": {
+    "hooks": {
+      "pre-commit": "lint-staged"
+    }
+  }
+}

+ 189 - 0
packages/ckeditor5-adapter-ckfinder/src/uploadadapter.js

@@ -0,0 +1,189 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/* globals XMLHttpRequest, FormData */
+
+/**
+ * @module adapter-ckfinder/uploadadapter
+ */
+
+import Plugin from '@ckeditor/ckeditor5-core/src/plugin';
+import FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';
+import { getCsrfToken } from './utils';
+
+/**
+ * A plugin that enables file uploads in CKEditor 5 using the CKFinder server–side connector.
+ *
+ * See the {@glink features/image-upload/ckfinder "CKFinder file manager integration" guide} to learn how to configure
+ * and use this feature as well as find out more about the full integration with the file manager
+ * provided by the {@link module:ckfinder/ckfinder~CKFinder} plugin.
+ *
+ * Check out the {@glink features/image-upload/image-upload comprehensive "Image upload overview"} to learn about
+ * other ways to upload images into CKEditor 5.
+ *
+ * @extends module:core/plugin~Plugin
+ */
+export default class CKFinderUploadAdapter extends Plugin {
+	/**
+	 * @inheritDoc
+	 */
+	static get requires() {
+		return [ FileRepository ];
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	static get pluginName() {
+		return 'CKFinderUploadAdapter';
+	}
+
+	/**
+	 * @inheritDoc
+	 */
+	init() {
+		const url = this.editor.config.get( 'ckfinder.uploadUrl' );
+
+		if ( !url ) {
+			return;
+		}
+
+		// Register CKFinderAdapter
+		this.editor.plugins.get( FileRepository ).createUploadAdapter = loader => new UploadAdapter( loader, url, this.editor.t );
+	}
+}
+
+/**
+ * Upload adapter for CKFinder.
+ *
+ * @private
+ * @implements module:upload/filerepository~UploadAdapter
+ */
+class UploadAdapter {
+	/**
+	 * Creates a new adapter instance.
+	 *
+	 * @param {module:upload/filerepository~FileLoader} loader
+	 * @param {String} url
+	 * @param {module:utils/locale~Locale#t} t
+	 */
+	constructor( loader, url, t ) {
+		/**
+		 * FileLoader instance to use during the upload.
+		 *
+		 * @member {module:upload/filerepository~FileLoader} #loader
+		 */
+		this.loader = loader;
+
+		/**
+		 * Upload URL.
+		 *
+		 * @member {String} #url
+		 */
+		this.url = url;
+
+		/**
+		 * Locale translation method.
+		 *
+		 * @member {module:utils/locale~Locale#t} #t
+		 */
+		this.t = t;
+	}
+
+	/**
+	 * Starts the upload process.
+	 *
+	 * @see module:upload/filerepository~UploadAdapter#upload
+	 * @returns {Promise.<Object>}
+	 */
+	upload() {
+		return this.loader.file.then( file => {
+			return new Promise( ( resolve, reject ) => {
+				this._initRequest();
+				this._initListeners( resolve, reject, file );
+				this._sendRequest( file );
+			} );
+		} );
+	}
+
+	/**
+	 * Aborts the upload process.
+	 *
+	 * @see module:upload/filerepository~UploadAdapter#abort
+	 */
+	abort() {
+		if ( this.xhr ) {
+			this.xhr.abort();
+		}
+	}
+
+	/**
+	 * Initializes the XMLHttpRequest object.
+	 *
+	 * @private
+	 */
+	_initRequest() {
+		const xhr = this.xhr = new XMLHttpRequest();
+
+		xhr.open( 'POST', this.url, true );
+		xhr.responseType = 'json';
+	}
+
+	/**
+	 * Initializes XMLHttpRequest listeners.
+	 *
+	 * @private
+	 * @param {Function} resolve Callback function to be called when the request is successful.
+	 * @param {Function} reject Callback function to be called when the request cannot be completed.
+	 * @param {File} file File instance to be uploaded.
+	 */
+	_initListeners( resolve, reject, file ) {
+		const xhr = this.xhr;
+		const loader = this.loader;
+		const t = this.t;
+		const genericError = t( 'Cannot upload file:' ) + ` ${ file.name }.`;
+
+		xhr.addEventListener( 'error', () => reject( genericError ) );
+		xhr.addEventListener( 'abort', () => reject() );
+		xhr.addEventListener( 'load', () => {
+			const response = xhr.response;
+
+			if ( !response || !response.uploaded ) {
+				return reject( response && response.error && response.error.message ? response.error.message : genericError );
+			}
+
+			resolve( {
+				default: response.url
+			} );
+		} );
+
+		// Upload progress when it's supported.
+		/* istanbul ignore else */
+		if ( xhr.upload ) {
+			xhr.upload.addEventListener( 'progress', evt => {
+				if ( evt.lengthComputable ) {
+					loader.uploadTotal = evt.total;
+					loader.uploaded = evt.loaded;
+				}
+			} );
+		}
+	}
+
+	/**
+	 * Prepares the data and sends the request.
+	 *
+	 * @private
+	 * @param {File} file File instance to be uploaded.
+	 */
+	_sendRequest( file ) {
+		// Prepare form data.
+		const data = new FormData();
+		data.append( 'upload', file );
+		data.append( 'ckCsrfToken', getCsrfToken() );
+
+		// Send request.
+		this.xhr.send( data );
+	}
+}

+ 83 - 0
packages/ckeditor5-adapter-ckfinder/src/utils.js

@@ -0,0 +1,83 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/* globals window, document */
+
+/**
+ * @module adapter-ckfinder/utils
+ */
+
+const TOKEN_COOKIE_NAME = 'ckCsrfToken';
+const TOKEN_LENGTH = 40;
+const tokenCharset = 'abcdefghijklmnopqrstuvwxyz0123456789';
+
+/**
+ * Returns the CSRF token value. The value is a hash stored in `document.cookie`
+ * under the `ckCsrfToken` key. The CSRF token can be used to secure the communication
+ * between the web browser and the CKFinder server.
+ *
+ * @returns {String}
+ */
+export function getCsrfToken() {
+	let token = getCookie( TOKEN_COOKIE_NAME );
+
+	if ( !token || token.length != TOKEN_LENGTH ) {
+		token = generateToken( TOKEN_LENGTH );
+		setCookie( TOKEN_COOKIE_NAME, token );
+	}
+
+	return token;
+}
+
+/**
+ * Returns the value of the cookie with a given name or `null` if the cookie is not found.
+ *
+ * @param {String} name
+ * @returns {String|null}
+ */
+export function getCookie( name ) {
+	name = name.toLowerCase();
+	const parts = document.cookie.split( ';' );
+
+	for ( const part of parts ) {
+		const pair = part.split( '=' );
+		const key = decodeURIComponent( pair[ 0 ].trim().toLowerCase() );
+
+		if ( key === name ) {
+			return decodeURIComponent( pair[ 1 ] );
+		}
+	}
+
+	return null;
+}
+
+/**
+ * Sets the value of the cookie with a given name.
+ *
+ * @param {String} name
+ * @param {String} value
+ */
+export function setCookie( name, value ) {
+	document.cookie = encodeURIComponent( name ) + '=' + encodeURIComponent( value ) + ';path=/';
+}
+
+// Generates the CSRF token with the given length.
+//
+// @private
+// @param {Number} length
+// @returns {string}
+function generateToken( length ) {
+	let result = '';
+	const randValues = new Uint8Array( length );
+
+	window.crypto.getRandomValues( randValues );
+
+	for ( let j = 0; j < randValues.length; j++ ) {
+		const character = tokenCharset.charAt( randValues[ j ] % tokenCharset.length );
+		result += Math.random() > 0.5 ? character.toUpperCase() : character;
+	}
+
+	return result;
+}

+ 4 - 0
packages/ckeditor5-adapter-ckfinder/tests/manual/uploadadapter.html

@@ -0,0 +1,4 @@
+<div id="editor">
+	<h2>Image upload</h2>
+	<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla finibus consequat placerat. Vestibulum id tellus et mauris sagittis tincidunt quis id mauris. Curabitur consectetur lectus sit amet tellus mattis, non lobortis leo interdum.</p>
+</div>

+ 42 - 0
packages/ckeditor5-adapter-ckfinder/tests/manual/uploadadapter.js

@@ -0,0 +1,42 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/* globals console, window, document */
+
+import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';
+import Enter from '@ckeditor/ckeditor5-enter/src/enter';
+import Typing from '@ckeditor/ckeditor5-typing/src/typing';
+import Paragraph from '@ckeditor/ckeditor5-paragraph/src/paragraph';
+import Heading from '@ckeditor/ckeditor5-heading/src/heading';
+import Image from '@ckeditor/ckeditor5-image/src/image';
+import ImageCaption from '@ckeditor/ckeditor5-image/src/imagecaption';
+import Undo from '@ckeditor/ckeditor5-undo/src/undo';
+import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
+import ImageToolbar from '@ckeditor/ckeditor5-image/src/imagetoolbar';
+import ImageStyle from '@ckeditor/ckeditor5-image/src/imagestyle';
+import Bold from '@ckeditor/ckeditor5-basic-styles/src/bold';
+import Italic from '@ckeditor/ckeditor5-basic-styles/src/italic';
+import List from '@ckeditor/ckeditor5-list/src/list';
+import ImageUpload from '@ckeditor/ckeditor5-image/src/imageupload';
+import CKFinderUploadAdapter from '../../src/uploadadapter';
+
+ClassicEditor
+	.create( document.querySelector( '#editor' ), {
+		plugins: [
+			Enter, Typing, Paragraph, Heading, Undo, Bold, Italic, Heading, List, Image, ImageToolbar, Clipboard,
+			ImageCaption, ImageStyle, ImageUpload, CKFinderUploadAdapter
+		],
+		toolbar: [ 'heading', '|', 'undo', 'redo', 'bold', 'italic', 'bulletedList', 'numberedList', 'imageUpload' ],
+		ckfinder: {
+			// eslint-disable-next-line max-len
+			uploadUrl: 'https://cksource.com/weuy2g4ryt278ywiue/core/connector/php/connector.php?command=QuickUpload&type=Files&responseType=json'
+		}
+	} )
+	.then( editor => {
+		window.editor = editor;
+	} )
+	.catch( err => {
+		console.error( err.stack );
+	} );

+ 10 - 0
packages/ckeditor5-adapter-ckfinder/tests/manual/uploadadapter.md

@@ -0,0 +1,10 @@
+## CKFinder upload adapter
+
+1. Drop an image into editor.
+1. Image should be read and displayed.
+1. Upload progress bar should be visible above the image.
+1. After uploading is complete your image should be replaced with sample image from server (use dev tools to check image src attribute).
+
+Repeat all the steps with:
+* dropping multiple images,
+* using toolbar button to add one and multiple images.

+ 213 - 0
packages/ckeditor5-adapter-ckfinder/tests/uploadadapter.js

@@ -0,0 +1,213 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/* globals document */
+import ClassicTestEditor from '@ckeditor/ckeditor5-core/tests/_utils/classictesteditor';
+
+import Clipboard from '@ckeditor/ckeditor5-clipboard/src/clipboard';
+import Image from '@ckeditor/ckeditor5-image/src/image';
+import ImageUpload from '@ckeditor/ckeditor5-image/src/imageupload';
+import CKFinderUploadAdapter from '../src/uploadadapter';
+import FileRepository from '@ckeditor/ckeditor5-upload/src/filerepository';
+import { createNativeFileMock } from '@ckeditor/ckeditor5-upload/tests/_utils/mocks';
+import testUtils from '@ckeditor/ckeditor5-core/tests/_utils/utils';
+
+describe( 'CKFinderUploadAdapter', () => {
+	let editor, sinonXHR, fileRepository, editorElement;
+	testUtils.createSinonSandbox();
+
+	beforeEach( () => {
+		editorElement = document.createElement( 'div' );
+		document.body.appendChild( editorElement );
+
+		sinonXHR = testUtils.sinon.useFakeServer();
+
+		return ClassicTestEditor
+			.create( editorElement, {
+				plugins: [ Clipboard, Image, ImageUpload, CKFinderUploadAdapter ],
+				ckfinder: {
+					uploadUrl: 'http://example.com'
+				}
+			} )
+			.then( newEditor => {
+				editor = newEditor;
+				fileRepository = editor.plugins.get( FileRepository );
+			} );
+	} );
+
+	afterEach( () => {
+		sinonXHR.restore();
+
+		if ( editorElement ) {
+			editorElement.remove();
+		}
+
+		if ( editor ) {
+			return editor.destroy();
+		}
+	} );
+
+	it( 'should be loaded', () => {
+		expect( editor.plugins.get( CKFinderUploadAdapter ) ).to.be.instanceOf( CKFinderUploadAdapter );
+	} );
+
+	describe( 'UploadAdapter', () => {
+		let adapter, loader;
+
+		beforeEach( () => {
+			const file = createNativeFileMock();
+			file.name = 'image.jpeg';
+
+			loader = fileRepository.createLoader( file );
+
+			adapter = editor.plugins.get( FileRepository ).createUploadAdapter( loader );
+		} );
+
+		it( 'crateAdapter method should be registered and have upload and abort methods', () => {
+			expect( adapter ).to.not.be.undefined;
+			expect( adapter.upload ).to.be.a( 'function' );
+			expect( adapter.abort ).to.be.a( 'function' );
+		} );
+
+		it( 'should not set the FileRepository.createUploadAdapter factory if not configured', () => {
+			const editorElement = document.createElement( 'div' );
+			document.body.appendChild( editorElement );
+
+			return ClassicTestEditor
+				.create( editorElement, {
+					plugins: [ Clipboard, Image, ImageUpload, CKFinderUploadAdapter ]
+				} )
+				.then( editor => {
+					const fileRepository = editor.plugins.get( FileRepository );
+
+					expect( fileRepository ).to.not.have.property( 'createUploadAdapter' );
+
+					editorElement.remove();
+
+					return editor.destroy();
+				} );
+		} );
+
+		describe( 'upload', () => {
+			it( 'should return promise', () => {
+				expect( adapter.upload() ).to.be.instanceof( Promise );
+			} );
+
+			it( 'should call url from config', () => {
+				let request;
+				const validResponse = {
+					uploaded: 1
+				};
+
+				adapter.upload();
+
+				return loader.file.then( () => {
+					request = sinonXHR.requests[ 0 ];
+					request.respond( 200, { 'Content-Type': 'application/json' }, JSON.stringify( validResponse ) );
+
+					expect( request.url ).to.equal( 'http://example.com' );
+				} );
+			} );
+
+			it( 'should throw an error on generic request error', () => {
+				const promise = adapter.upload()
+					.then( () => {
+						throw new Error( 'Promise should throw.' );
+					} )
+					.catch( msg => {
+						expect( msg ).to.equal( 'Cannot upload file: image.jpeg.' );
+					} );
+
+				loader.file.then( () => {
+					const request = sinonXHR.requests[ 0 ];
+					request.error();
+				} );
+
+				return promise;
+			} );
+
+			it( 'should throw an error on error from server', () => {
+				const responseError = {
+					error: {
+						message: 'Foo bar baz.'
+					}
+				};
+
+				const promise = adapter.upload()
+					.then( () => {
+						throw new Error( 'Promise should throw.' );
+					} )
+					.catch( msg => {
+						expect( msg ).to.equal( 'Foo bar baz.' );
+					} );
+
+				loader.file.then( () => {
+					const request = sinonXHR.requests[ 0 ];
+					request.respond( 200, { 'Content-Type': 'application/json' }, JSON.stringify( responseError ) );
+				} );
+
+				return promise;
+			} );
+
+			it( 'should throw a generic error on error from server without message', () => {
+				const responseError = {
+					error: {}
+				};
+
+				const promise = adapter.upload()
+					.then( () => {
+						throw new Error( 'Promise should throw.' );
+					} )
+					.catch( msg => {
+						expect( msg ).to.equal( 'Cannot upload file: image.jpeg.' );
+					} );
+
+				loader.file.then( () => {
+					const request = sinonXHR.requests[ 0 ];
+					request.respond( 200, { 'Content-Type': 'application/json' }, JSON.stringify( responseError ) );
+				} );
+
+				return promise;
+			} );
+
+			it( 'should throw an error on abort', () => {
+				let request;
+
+				const promise = adapter.upload()
+					.then( () => {
+						throw new Error( 'Promise should throw.' );
+					} )
+					.catch( () => {
+						expect( request.aborted ).to.be.true;
+					} );
+
+				loader.file.then( () => {
+					request = sinonXHR.requests[ 0 ];
+					adapter.abort();
+				} );
+
+				return promise;
+			} );
+
+			it( 'abort should not throw before upload', () => {
+				expect( () => {
+					adapter.abort();
+				} ).to.not.throw();
+			} );
+
+			it( 'should update progress', () => {
+				adapter.upload();
+
+				return loader.file.then( () => {
+					const request = sinonXHR.requests[ 0 ];
+					request.uploadProgress( { loaded: 4, total: 10 } );
+
+					expect( loader.uploadTotal ).to.equal( 10 );
+					expect( loader.uploaded ).to.equal( 4 );
+				} );
+			} );
+		} );
+	} );
+} );

+ 72 - 0
packages/ckeditor5-adapter-ckfinder/tests/utils.js

@@ -0,0 +1,72 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/* globals document */
+
+import { getCsrfToken, getCookie, setCookie } from '../src/utils';
+
+describe( 'utils', () => {
+	beforeEach( () => {
+		clearCookie( 'ckCsrfToken' );
+	} );
+
+	describe( 'getCsrfToken', () => {
+		let token;
+
+		beforeEach( () => {
+			token = getCsrfToken();
+		} );
+
+		it( 'should be saved in cookie', () => {
+			expect( document.cookie.indexOf( `ckCsrfToken=${ token }` ) > -1 ).to.be.true;
+		} );
+
+		it( 'should have proper length', () => {
+			expect( token.length ).to.equal( 40 );
+		} );
+
+		it( 'should produce same token for all cals', () => {
+			expect( token ).to.equal( getCsrfToken() );
+		} );
+	} );
+
+	describe( 'get/set cookie', () => {
+		let cookieName, cookieValue;
+
+		beforeEach( () => {
+			cookieName = 'test-cookie-name';
+			cookieValue = 'test-value' + Math.random();
+
+			clearCookie( cookieName );
+		} );
+
+		describe( 'setCookie', () => {
+			it( 'should set cookie', () => {
+				setCookie( cookieName, cookieValue );
+				expect( document.cookie.indexOf( `${ cookieName }=${ cookieValue }` ) > -1 ).to.be.true;
+			} );
+		} );
+
+		describe( 'getCookie', () => {
+			it( 'should get cookie', () => {
+				document.cookie = encodeURIComponent( cookieName ) + '=' + encodeURIComponent( cookieValue ) + ';path=/';
+				expect( getCookie( cookieName ) ).to.equal( cookieValue );
+			} );
+
+			it( 'should return null if cookie is not present', () => {
+				expect( getCookie( cookieName ) ).to.be.null;
+			} );
+
+			it( 'should return empty cookie', () => {
+				document.cookie = encodeURIComponent( cookieName ) + '=;path=/';
+				expect( getCookie( cookieName ) ).to.equal( '' );
+			} );
+		} );
+	} );
+} );
+
+function clearCookie( name ) {
+	document.cookie = `${ name }=;expires=Thu, 01 Jan 1970 00:00:00 GMT`;
+}

+ 16 - 0
packages/ckeditor5-alignment/.editorconfig

@@ -0,0 +1,16 @@
+# Configurations to normalize the IDE behavior.
+# http://editorconfig.org/
+
+root = true
+
+[*]
+indent_style = tab
+tab_width = 4
+charset = utf-8
+end_of_line = lf
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[package.json]
+indent_style = space
+tab_width = 2

+ 12 - 0
packages/ckeditor5-alignment/.eslintrc.js

@@ -0,0 +1,12 @@
+/**
+ * @license Copyright (c) 2003-2020, CKSource - Frederico Knabben. All rights reserved.
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
+ */
+
+/* eslint-env node */
+
+'use strict';
+
+module.exports = {
+	extends: 'ckeditor5'
+};

+ 18 - 0
packages/ckeditor5-alignment/.gitattributes

@@ -0,0 +1,18 @@
+*			text=auto
+
+*.htaccess	eol=lf
+*.cgi		eol=lf
+*.sh		eol=lf
+
+*.css		text
+*.htm		text
+*.html		text
+*.js		text
+*.json		text
+*.php		text
+*.txt		text
+*.md		text
+
+*.png		-text
+*.gif		-text
+*.jpg		-text

+ 9 - 0
packages/ckeditor5-alignment/.github/PULL_REQUEST_TEMPLATE.md

@@ -0,0 +1,9 @@
+### Suggested merge commit message ([convention](https://github.com/ckeditor/ckeditor5-design/wiki/Git-commit-message-convention))
+
+Type: Message. Closes ckeditor/ckeditor5#000.
+
+---
+
+### Additional information
+
+*For example – encountered issues, assumptions you had to make, other affected tickets, etc.*

+ 1 - 0
packages/ckeditor5-alignment/.gitignore

@@ -0,0 +1 @@
+node_modules/

+ 3 - 0
packages/ckeditor5-alignment/.stylelintrc

@@ -0,0 +1,3 @@
+{
+	"extends": "stylelint-config-ckeditor5"
+}

部分文件因文件數量過多而無法顯示