mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-15 02:23:58 +00:00
Continue links
This isn't as simple as just dropping applyToAppendedContent = false on LinkAnnotation, because browsers differ in their continuation behavior. Firefox continues links, but Chrome doesn't. To work around this, add a property indicating that the annotation needs its continuation behavior to be forced. Rename areAnnotationsCorrect() to needsPawn() accordingly. Bug: 49931 Change-Id: Id6424af89c92bba2be87736e8a937e0f2067c007
This commit is contained in:
parent
0ffc4d15ca
commit
f9864e9288
|
@ -33,6 +33,8 @@ ve.ce.LinkAnnotation.static.name = 'link';
|
|||
|
||||
ve.ce.LinkAnnotation.static.tagName = 'a';
|
||||
|
||||
ve.ce.LinkAnnotation.static.forceContinuation = true;
|
||||
|
||||
/* Registration */
|
||||
|
||||
ve.ce.annotationFactory.register( ve.ce.LinkAnnotation );
|
||||
|
|
|
@ -32,3 +32,15 @@ ve.inheritClass( ve.ce.Annotation, ve.ce.View );
|
|||
/* Static Properties */
|
||||
|
||||
ve.ce.Annotation.static.tagName = 'span';
|
||||
|
||||
/**
|
||||
* Whether this annotation's continuation (or lack thereof) needs to be forced.
|
||||
*
|
||||
* This should be set to true only for annotations that aren't continued by browsers but are in DM,
|
||||
* or the other way around, or those where behavior is inconsistent between browsers.
|
||||
*
|
||||
* @property static.forceContinuation
|
||||
* @static
|
||||
* @inheritable
|
||||
*/
|
||||
ve.ce.Annotation.static.forceContinuation = false;
|
||||
|
|
|
@ -21,6 +21,20 @@ ve.ce.AnnotationFactory = function VeCeAnnotationFactory() {
|
|||
|
||||
ve.inheritClass( ve.ce.AnnotationFactory, ve.NamedClassFactory );
|
||||
|
||||
/* Methods */
|
||||
|
||||
/**
|
||||
* Check if an annotation needs to force continuation
|
||||
* @param {string} type Annotation type
|
||||
* @returns {boolean} Whether the annotation needs to force continuation
|
||||
*/
|
||||
ve.ce.AnnotationFactory.prototype.isAnnotationContinuationForced = function ( type ) {
|
||||
if ( type in this.registry ) {
|
||||
return this.registry[type].static.forceContinuation;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/* Initialization */
|
||||
|
||||
// TODO: Move instantiation to a different file
|
||||
|
|
|
@ -1071,8 +1071,8 @@ ve.ce.Surface.prototype.handleInsertion = function () {
|
|||
|
||||
if ( selection.isCollapsed() ) {
|
||||
slug = this.documentView.getSlugAtOffset( selection.start );
|
||||
// Is this a slug or are the annotations incorrect?
|
||||
if ( slug || !this.areAnnotationsCorrect( selection, insertionAnnotations ) ) {
|
||||
// Always pawn in a slug
|
||||
if ( slug || this.needsPawn( selection, insertionAnnotations ) ) {
|
||||
placeholder = '♙';
|
||||
if ( !insertionAnnotations.isEmpty() ) {
|
||||
placeholder = [placeholder, insertionAnnotations.getIndexes()];
|
||||
|
@ -1442,33 +1442,55 @@ ve.ce.Surface.prototype.getClickCount = function ( e ) {
|
|||
};
|
||||
|
||||
/**
|
||||
* Checks if related annotationSet matches insertionAnnotations.
|
||||
* Checks if we need to pawn for insertionAnnotations based on the related annotationSet.
|
||||
*
|
||||
* "Related" is typically to the left, unless at the beginning of a node.
|
||||
*
|
||||
* We choose to pawn if the related annotationSet doesn't match insertionAnnotations, or if
|
||||
* we are at the edge of an annotation that requires pawning (i.e. an annotation requiring pawning
|
||||
* is present on the left but not on the right, or vice versa).
|
||||
*
|
||||
* @method
|
||||
* @param {ve.Range} selection
|
||||
* @returns {ve.dm.AnnotationSet} insertionAnnotations
|
||||
* @param {ve.dm.AnnotationSet} insertionAnnotations
|
||||
* @returns {boolean} Whether we need to pawn
|
||||
*/
|
||||
ve.ce.Surface.prototype.areAnnotationsCorrect = function ( selection, insertionAnnotations ) {
|
||||
var documentModel = this.model.documentModel;
|
||||
ve.ce.Surface.prototype.needsPawn = function ( selection, insertionAnnotations ) {
|
||||
var leftAnnotations, rightAnnotations, documentModel = this.model.documentModel;
|
||||
|
||||
function isForced( annotation ) {
|
||||
return ve.ce.annotationFactory.isAnnotationContinuationForced( annotation.constructor.static.name );
|
||||
}
|
||||
|
||||
if ( selection.start > 0 ) {
|
||||
leftAnnotations = documentModel.data.getAnnotationsFromOffset( selection.start - 1 );
|
||||
}
|
||||
if ( selection.start < documentModel.data.getLength() ) {
|
||||
rightAnnotations = documentModel.data.getAnnotationsFromOffset( selection.start + 1 );
|
||||
}
|
||||
|
||||
// Take annotations from the left
|
||||
if (
|
||||
selection.start > 0 &&
|
||||
!documentModel.data.getAnnotationsFromOffset( selection.start - 1 ).compareTo( insertionAnnotations )
|
||||
) {
|
||||
return false;
|
||||
// TODO reorganize the logic in this function
|
||||
if ( leftAnnotations && !leftAnnotations.compareTo( insertionAnnotations ) ) {
|
||||
return true;
|
||||
}
|
||||
// At the beginning of a node, take from the right
|
||||
if (
|
||||
rangy.getSelection( this.$document[0] ).anchorOffset === 0 &&
|
||||
selection.start < this.model.getDocument().data.getLength() &&
|
||||
!documentModel.data.getAnnotationsFromOffset( selection.start + 1 ).compareTo( insertionAnnotations )
|
||||
rightAnnotations &&
|
||||
!rightAnnotations.compareTo( insertionAnnotations )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
leftAnnotations && rightAnnotations &&
|
||||
!leftAnnotations.filter( isForced ).compareTo( rightAnnotations.filter( isForced ) )
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/*! Getters */
|
||||
|
|
|
@ -30,8 +30,6 @@ ve.dm.LinkAnnotation.static.name = 'link';
|
|||
|
||||
ve.dm.LinkAnnotation.static.matchTagNames = ['a'];
|
||||
|
||||
ve.dm.LinkAnnotation.static.applyToAppendedContent = false;
|
||||
|
||||
ve.dm.LinkAnnotation.static.toDataElement = function ( domElements ) {
|
||||
return {
|
||||
'type': 'link',
|
||||
|
|
Loading…
Reference in a new issue