-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7386 from ckeditor/i/7330
Feature (link): Introduced the linking images feature. Closes #7330.
- Loading branch information
Showing
15 changed files
with
843 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/** | ||
* @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 link/linkimage | ||
*/ | ||
|
||
import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; | ||
import LinkImageEditing from './linkimageediting'; | ||
import LinkImageUI from './linkimageui'; | ||
|
||
/** | ||
* The `LinkImage` plugin. | ||
* | ||
* This is a "glue" plugin that loads the {@link module:link/linkimageediting~LinkImageEditing link image editing feature} | ||
* and {@link module:link/linkimageui~LinkImageUI linkimage UI feature}. | ||
* | ||
* @extends module:core/plugin~Plugin | ||
*/ | ||
export default class LinkImage extends Plugin { | ||
/** | ||
* @inheritDoc | ||
*/ | ||
static get requires() { | ||
return [ LinkImageEditing, LinkImageUI ]; | ||
} | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
static get pluginName() { | ||
return 'LinkImage'; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
/** | ||
* @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 link/linkimageediting | ||
*/ | ||
|
||
import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; | ||
import ImageEditing from '@ckeditor/ckeditor5-image/src/image/imageediting'; | ||
import LinkEditing from './linkediting'; | ||
|
||
/** | ||
* The link image engine feature. | ||
* | ||
* It accepts the `linkHref="url"` attribute in the model for the {@link module:image/image~Image `<image>`} element | ||
* which allows linking images. | ||
* | ||
* @extends module:core/plugin~Plugin | ||
*/ | ||
export default class LinkImageEditing extends Plugin { | ||
/** | ||
* @inheritDoc | ||
*/ | ||
static get requires() { | ||
return [ ImageEditing, LinkEditing ]; | ||
} | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
static get pluginName() { | ||
return 'LinkImageEditing'; | ||
} | ||
|
||
init() { | ||
const editor = this.editor; | ||
|
||
editor.model.schema.extend( 'image', { allowAttributes: [ 'linkHref' ] } ); | ||
|
||
editor.conversion.for( 'upcast' ).add( upcastLink() ); | ||
editor.conversion.for( 'downcast' ).add( downcastImageLink() ); | ||
} | ||
} | ||
|
||
// Returns a converter that consumes the 'href' attribute if a link contains an image. | ||
// | ||
// @private | ||
// @returns {Function} | ||
// | ||
function upcastLink() { | ||
return dispatcher => { | ||
dispatcher.on( 'element:a', ( evt, data, conversionApi ) => { | ||
const viewLink = data.viewItem; | ||
const imageInLink = Array.from( viewLink.getChildren() ).find( child => child.name === 'img' ); | ||
|
||
if ( !imageInLink ) { | ||
return; | ||
} | ||
|
||
// There's an image inside an <a> element - we consume it so it won't be picked up by the Link plugin. | ||
const consumableAttributes = { attributes: [ 'href' ] }; | ||
|
||
// Consume the `href` attribute so the default one will not convert it to $text attribute. | ||
if ( !conversionApi.consumable.consume( viewLink, consumableAttributes ) ) { | ||
// Might be consumed by something else - i.e. other converter with priority=highest - a standard check. | ||
return; | ||
} | ||
|
||
const linkHref = viewLink.getAttribute( 'href' ); | ||
|
||
// Missing the 'href' attribute. | ||
if ( !linkHref ) { | ||
return; | ||
} | ||
|
||
// A full definition of the image feature. | ||
// figure > a > img: parent of the link element is an image element. | ||
let modelElement = data.modelCursor.parent; | ||
|
||
if ( !modelElement.is( 'image' ) ) { | ||
// a > img: parent of the link is not the image element. We need to convert it manually. | ||
const conversionResult = conversionApi.convertItem( imageInLink, data.modelCursor ); | ||
|
||
// Set image range as conversion result. | ||
data.modelRange = conversionResult.modelRange; | ||
|
||
// Continue conversion where image conversion ends. | ||
data.modelCursor = conversionResult.modelCursor; | ||
|
||
modelElement = data.modelCursor.nodeBefore; | ||
} | ||
|
||
if ( modelElement && modelElement.is( 'image' ) ) { | ||
// Set the linkHref attribute from link element on model image element. | ||
conversionApi.writer.setAttribute( 'linkHref', linkHref, modelElement ); | ||
} | ||
}, { priority: 'high' } ); | ||
}; | ||
} | ||
|
||
// Return a converter that adds the `<a>` element to data. | ||
// | ||
// @private | ||
// @returns {Function} | ||
// | ||
function downcastImageLink() { | ||
return dispatcher => { | ||
dispatcher.on( 'attribute:linkHref:image', ( evt, data, conversionApi ) => { | ||
// The image will be already converted - so it will be present in the view. | ||
const viewFigure = conversionApi.mapper.toViewElement( data.item ); | ||
const writer = conversionApi.writer; | ||
|
||
// But we need to check whether the link element exists. | ||
const linkInImage = Array.from( viewFigure.getChildren() ).find( child => child.name === 'a' ); | ||
|
||
// If so, update the attribute if it's defined or remove the entire link if the attribute is empty. | ||
if ( linkInImage ) { | ||
if ( data.attributeNewValue ) { | ||
writer.setAttribute( 'href', data.attributeNewValue, linkInImage ); | ||
} else { | ||
const viewImage = Array.from( linkInImage.getChildren() ).find( child => child.name === 'img' ); | ||
|
||
writer.move( writer.createRangeOn( viewImage ), writer.createPositionAt( viewFigure, 0 ) ); | ||
writer.remove( linkInImage ); | ||
} | ||
} else { | ||
// But if it does not exist. Let's wrap already converted image by newly created link element. | ||
// 1. Create an empty link element. | ||
const linkElement = writer.createContainerElement( 'a', { href: data.attributeNewValue } ); | ||
|
||
// 2. Insert link inside the associated image. | ||
writer.insert( writer.createPositionAt( viewFigure, 0 ), linkElement ); | ||
|
||
// 3. Move the image to the link. | ||
writer.move( writer.createRangeOn( viewFigure.getChild( 1 ) ), writer.createPositionAt( linkElement, 0 ) ); | ||
} | ||
} ); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
/** | ||
* @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 link/linkimageui | ||
*/ | ||
|
||
import Plugin from '@ckeditor/ckeditor5-core/src/plugin'; | ||
import Image from '@ckeditor/ckeditor5-image/src/image'; | ||
import LinkUI from './linkui'; | ||
import LinkEditing from './linkediting'; | ||
|
||
/** | ||
* The link image UI plugin. | ||
* | ||
* TODO: Docs. | ||
* | ||
* @extends module:core/plugin~Plugin | ||
*/ | ||
export default class LinkImageUI extends Plugin { | ||
/** | ||
* @inheritDoc | ||
*/ | ||
static get requires() { | ||
return [ Image, LinkEditing, LinkUI ]; | ||
} | ||
|
||
/** | ||
* @inheritDoc | ||
*/ | ||
static get pluginName() { | ||
return 'LinkImageUI'; | ||
} | ||
|
||
init() { | ||
} | ||
} |
Oops, something went wrong.