Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge branch 'master' into t/ckeditor5/1684
Browse files Browse the repository at this point in the history
  • Loading branch information
jodator committed Aug 5, 2019
2 parents 16fe1e7 + 0c2124f commit 0044b79
Show file tree
Hide file tree
Showing 20 changed files with 286 additions and 200 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
@@ -1,6 +1,16 @@
Changelog
=========

## [13.1.2](https://github.com/ckeditor/ckeditor5-image/compare/v13.1.1...v13.1.2) (2019-07-10)

Internal changes only (updated dependencies, documentation, etc.).


## [13.1.1](https://github.com/ckeditor/ckeditor5-image/compare/v13.1.0...v13.1.1) (2019-07-04)

Internal changes only (updated dependencies, documentation, etc.).


## [13.1.0](https://github.com/ckeditor/ckeditor5-image/compare/v13.0.1...v13.1.0) (2019-06-05)

### Bug fixes
Expand Down
14 changes: 11 additions & 3 deletions docs/framework/guides/deep-dive/upload-adapter.md
Expand Up @@ -10,6 +10,10 @@ In this guide you will learn the basic concepts of the file upload architecture

While this guide is mainly focused on the image upload (the most common kind of upload), keep in mind that the presented concepts and the API allow developing all sorts of file upload adapters for different file types like PDFs, movies, etc.

<info-box>
If you do not feel like getting through this guide but you want a simple upload adapter that works, check out the {@link features/simple-upload-adapter Simple upload adapter} plugin we implemented for you.
</info-box>

<info-box>
Check out the comprehensive {@link features/image-upload Image upload overview} to learn about other ways to upload images into CKEditor 5.
</info-box>
Expand Down Expand Up @@ -152,13 +156,17 @@ editor.plugins.get( 'FileRepository' ).createUploadAdapter = ( loader ) => {
In this section, you are going to implement and enable a custom upload adapter. The adapter will use the native [`XMLHttpRequest`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) to send files returned by the loader to a pre–configured URL on the server, handling the `error`, `abort`, `load`, and `progress` events fired by the request.

<info-box>
Note that this is just an example implementation and `XMLHttpRequest` might not necessarily be the best solution for your application.
If you do not feel like getting through this guide but you want a simple `XMLHttpRequest`–based upload adapter that works, check out the {@link features/simple-upload-adapter Simple upload adapter} plugin we implemented for you. It comes with pretty much the same functionality. Just install it, configure it, and you are ready to go.
</info-box>

Use the provided code snippets as an inspiration for your own custom upload adapter &mdash; it is up to you to choose the technologies and APIs to use. For instance, you may want to check out the native [`fetch()` API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) that works with `Promises` out of the box.
<info-box>
If the {@link features/simple-upload-adapter Simple upload adapter} is not enough for you and you want a custom upload adapter developed on top this guide, go straight to the [full source code](#the-complete-implementation) and start experimenting.
</info-box>

<info-box>
If you do not want to read through this entire guide, you can simply go and check out the [full source code](#the-complete-implementation) of an `XMLHttpRequest`–based upload adapter that you can use in your application.
Note that this is just an example implementation and `XMLHttpRequest` might not necessarily be the best solution for your application.

Use the provided code snippets as an inspiration for your own custom upload adapter &mdash; it is up to you to choose the technologies and APIs to use. For instance, you may want to check out the native [`fetch()` API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) that works with `Promises` out of the box.
</info-box>

To start off, define the `MyUploadAdapter` class with its constructor.
Expand Down
36 changes: 18 additions & 18 deletions package.json
@@ -1,6 +1,6 @@
{
"name": "@ckeditor/ckeditor5-image",
"version": "13.1.0",
"version": "13.1.2",
"description": "Image feature for CKEditor 5.",
"keywords": [
"ckeditor",
Expand All @@ -10,26 +10,26 @@
"ckeditor5-plugin"
],
"dependencies": {
"@ckeditor/ckeditor5-core": "^12.1.1",
"@ckeditor/ckeditor5-engine": "^13.1.1",
"@ckeditor/ckeditor5-ui": "^13.0.0",
"@ckeditor/ckeditor5-upload": "^11.0.2",
"@ckeditor/ckeditor5-utils": "^12.1.1",
"@ckeditor/ckeditor5-widget": "^11.0.2"
"@ckeditor/ckeditor5-core": "^12.2.1",
"@ckeditor/ckeditor5-engine": "^13.2.1",
"@ckeditor/ckeditor5-ui": "^13.0.2",
"@ckeditor/ckeditor5-upload": "^11.1.1",
"@ckeditor/ckeditor5-utils": "^13.0.1",
"@ckeditor/ckeditor5-widget": "^11.0.4"
},
"devDependencies": {
"@ckeditor/ckeditor5-basic-styles": "^11.1.1",
"@ckeditor/ckeditor5-clipboard": "^11.0.2",
"@ckeditor/ckeditor5-editor-classic": "^12.1.1",
"@ckeditor/ckeditor5-enter": "^11.0.2",
"@ckeditor/ckeditor5-heading": "^11.0.2",
"@ckeditor/ckeditor5-link": "^11.0.2",
"@ckeditor/ckeditor5-list": "^12.0.2",
"@ckeditor/ckeditor5-paragraph": "^11.0.2",
"@ckeditor/ckeditor5-typing": "^12.0.2",
"@ckeditor/ckeditor5-undo": "^11.0.2",
"@ckeditor/ckeditor5-basic-styles": "^11.1.3",
"@ckeditor/ckeditor5-clipboard": "^12.0.1",
"@ckeditor/ckeditor5-editor-classic": "^12.1.3",
"@ckeditor/ckeditor5-enter": "^11.0.4",
"@ckeditor/ckeditor5-heading": "^11.0.4",
"@ckeditor/ckeditor5-link": "^11.1.1",
"@ckeditor/ckeditor5-list": "^12.0.4",
"@ckeditor/ckeditor5-paragraph": "^11.0.4",
"@ckeditor/ckeditor5-typing": "^12.1.1",
"@ckeditor/ckeditor5-undo": "^11.0.4",
"eslint": "^5.5.0",
"eslint-config-ckeditor5": "^1.0.11",
"eslint-config-ckeditor5": "^2.0.0",
"husky": "^1.3.1",
"lint-staged": "^7.0.0"
},
Expand Down
7 changes: 4 additions & 3 deletions src/imagestyle/utils.js
Expand Up @@ -7,12 +7,13 @@
* @module image/imagestyle/utils
*/

import log from '@ckeditor/ckeditor5-utils/src/log';
/* globals console */

import fullWidthIcon from '@ckeditor/ckeditor5-core/theme/icons/object-full-width.svg';
import leftIcon from '@ckeditor/ckeditor5-core/theme/icons/object-left.svg';
import centerIcon from '@ckeditor/ckeditor5-core/theme/icons/object-center.svg';
import rightIcon from '@ckeditor/ckeditor5-core/theme/icons/object-right.svg';
import { attachLinkToDocumentation } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';

/**
* Default image styles provided by the plugin that can be referred in the
Expand Down Expand Up @@ -115,8 +116,8 @@ function _normalizeStyle( style ) {
}
// If it's just a name but none of the defaults, warn because probably it's a mistake.
else {
log.warn(
'image-style-not-found: There is no such image style of given name.',
console.warn(
attachLinkToDocumentation( 'image-style-not-found: There is no such image style of given name.' ),
{ name: styleName }
);

Expand Down
20 changes: 16 additions & 4 deletions src/imagetextalternative/imagetextalternativeui.js
Expand Up @@ -163,7 +163,7 @@ export default class ImageTextAlternativeUI extends Plugin {
const command = editor.commands.get( 'imageTextAlternative' );
const labeledInput = this._form.labeledInput;

if ( !this._balloon.hasView( this._form ) ) {
if ( !this._isInBalloon ) {
this._balloon.add( {
view: this._form,
position: getBalloonPositionData( editor )
Expand All @@ -187,13 +187,15 @@ export default class ImageTextAlternativeUI extends Plugin {
* @private
*/
_hideForm( focusEditable ) {
if ( !this._isVisible ) {
if ( !this._isInBalloon ) {
return;
}

// Blur the input element before removing it from DOM to prevent issues in some browsers.
// See https://github.com/ckeditor/ckeditor5/issues/1501.
this._form.saveButtonView.focus();
if ( this._form.focusTracker.isFocused ) {
this._form.saveButtonView.focus();
}

this._balloon.remove( this._form );

Expand All @@ -209,6 +211,16 @@ export default class ImageTextAlternativeUI extends Plugin {
* @type {Boolean}
*/
get _isVisible() {
return this._balloon.visibleView == this._form;
return this._balloon.visibleView === this._form;
}

/**
* Returns `true` when the {@link #_form} is in the {@link #_balloon}.
*
* @private
* @type {Boolean}
*/
get _isInBalloon() {
return this._balloon.hasView( this._form );
}
}
20 changes: 10 additions & 10 deletions tests/image.js
Expand Up @@ -63,11 +63,11 @@ describe( 'Image', () => {

describe( 'selection', () => {
it( 'should create fake selection', () => {
setModelData( model, '[<image alt="alt text" src="foo.png"></image>]' );
setModelData( model, '[<image alt="alt text" src="/assets/sample.png"></image>]' );

expect( getViewData( view ) ).to.equal(
'[<figure class="ck-widget ck-widget_selected image" contenteditable="false">' +
'<img alt="alt text" src="foo.png"></img>' +
'<img alt="alt text" src="/assets/sample.png"></img>' +
'</figure>]'
);

Expand All @@ -76,11 +76,11 @@ describe( 'Image', () => {
} );

it( 'should create proper fake selection label when alt attribute is empty', () => {
setModelData( model, '[<image src="foo.png" alt=""></image>]' );
setModelData( model, '[<image src="/assets/sample.png" alt=""></image>]' );

expect( getViewData( view ) ).to.equal(
'[<figure class="ck-widget ck-widget_selected image" contenteditable="false">' +
'<img alt="" src="foo.png"></img>' +
'<img alt="" src="/assets/sample.png"></img>' +
'</figure>]'
);

Expand All @@ -90,16 +90,16 @@ describe( 'Image', () => {

it( 'should remove selected class from previously selected element', () => {
setModelData( model,
'[<image src="foo.png" alt="alt text"></image>]' +
'<image src="foo.png" alt="alt text"></image>'
'[<image src="/assets/sample.png" alt="alt text"></image>]' +
'<image src="/assets/sample.png" alt="alt text"></image>'
);

expect( getViewData( view ) ).to.equal(
'[<figure class="ck-widget ck-widget_selected image" contenteditable="false">' +
'<img alt="alt text" src="foo.png"></img>' +
'<img alt="alt text" src="/assets/sample.png"></img>' +
'</figure>]' +
'<figure class="ck-widget image" contenteditable="false">' +
'<img alt="alt text" src="foo.png"></img>' +
'<img alt="alt text" src="/assets/sample.png"></img>' +
'</figure>'
);

Expand All @@ -110,10 +110,10 @@ describe( 'Image', () => {

expect( getViewData( view ) ).to.equal(
'<figure class="ck-widget image" contenteditable="false">' +
'<img alt="alt text" src="foo.png"></img>' +
'<img alt="alt text" src="/assets/sample.png"></img>' +
'</figure>' +
'[<figure class="ck-widget ck-widget_selected image" contenteditable="false">' +
'<img alt="alt text" src="foo.png"></img>' +
'<img alt="alt text" src="/assets/sample.png"></img>' +
'</figure>]'
);
} );
Expand Down
16 changes: 8 additions & 8 deletions tests/image/converters.js
Expand Up @@ -88,9 +88,9 @@ describe( 'Image converters', () => {
} );

it( 'should find img element among children and convert it using already defined converters', () => {
editor.setData( '<figure class="image"><img src="foo.png" /></figure>' );
editor.setData( '<figure class="image"><img src="/assets/sample.png" /></figure>' );

expectModel( '<image src="foo.png"></image>' );
expectModel( '<image src="/assets/sample.png"></image>' );
expect( imgConverterCalled ).to.be.true;
} );

Expand All @@ -102,10 +102,10 @@ describe( 'Image converters', () => {
// Is allowed in root, but should not try to split image element.
schema.register( 'bar', { allowIn: '$root' } );

editor.setData( '<figure class="image">x<img src="foo.png" />y<foo></foo><bar></bar></figure>' );
editor.setData( '<figure class="image">x<img src="/assets/sample.png" />y<foo></foo><bar></bar></figure>' );

// Element bar not converted because schema does not allow it.
expectModel( '<image src="foo.png">xy<foo></foo></image>' );
expectModel( '<image src="/assets/sample.png">xy<foo></foo></image>' );
} );

it( 'should split parent element when image is not allowed - in the middle', () => {
Expand Down Expand Up @@ -178,18 +178,18 @@ describe( 'Image converters', () => {
data.modelCursor = data.modelRange.end;
}, { priority: 'high' } );

editor.setData( '<figure class="image"><img src="foo.png" />xyz</figure>' );
editor.setData( '<figure class="image"><img src="/assets/sample.png" />xyz</figure>' );

expectModel( '<myImage data="{"src":"foo.png"}"></myImage>' );
expectModel( '<myImage data="{"src":"/assets/sample.png"}"></myImage>' );
} );

// Test exactly what figure converter does, which is putting it's children element to image element.
// If this has not been done, it means that figure converter was not used.
it( 'should not convert if figure do not have class="image" attribute', () => {
editor.setData( '<figure><img src="foo.png" />xyz</figure>' );
editor.setData( '<figure><img src="/assets/sample.png" />xyz</figure>' );

// Default image converter will be fired.
expectModel( '<image src="foo.png"></image>' );
expectModel( '<image src="/assets/sample.png"></image>' );
} );

it( 'should not convert if there is no img element among children', () => {
Expand Down

0 comments on commit 0044b79

Please sign in to comment.