Page MenuHomePhabricator

Link cartouches interfere with browsers' word break algorithms
Open, LowestPublic40 Estimated Story Points

Description

In some cases VisualEditor can break a line before a space. Example from the article Arquitectura de Barcelona in the Catalan Wikipedia—it's the second thing marked in red, "l'edat mitjana de l'art":

arquitectura.png (921×1 px, 516 KB)

Spaces usually don't appear in the beginning of a line in the middle of a paragraph, but are always kept in the previous line. I guess that VE's deep breaking of all text into separate HTML elements is to blame.

Event Timeline

Jdforrester-WMF subscribed.

The line breaking is done by the browsers, not by VE. Possibly we're hinting it poorly?

I'm not really sure what's the issue, but I am pretty sure that it consistently happens with VE and never when the page is rendered for reading:

Arquitectura de Barcelona - Viquipèdia, l'enciclopèdia lliure 2016-05-06 20-24-22.png (921×1 px, 538 KB)

Maybe a comparison of HTML will help.

This is the HTML when it's rendered for reading:

fins al sorgiment en l'<a href="/wiki/Edat_mitjana" title="Edat mitjana">edat mitjana</a> de l'art

This is the HTML when it's rendered for editing in VE:

fins al sorgiment en l'<img class="ve-ce-nail ve-ce-nail-pre-open" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="><a title="Edat mitjana" href="https://ca.wikipedia.org/wiki/Edat_mitjana" class="ve-ce-linkAnnotation ve-ce-mwInternalLinkAnnotation"><img class="ve-ce-nail ve-ce-nail-post-open" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=">edat mitjana<img class="ve-ce-nail ve-ce-nail-pre-close" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="></a><img class="ve-ce-nail ve-ce-nail-post-close" src="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs="> de l'art

There are <img> tags there, and I'm not sure what are they for. May @dchan knows?

For the link cursoring behaviour we have invisible images either side of a link, this causes the browser's word break algorithm to treat them as breaks. It may not be fixable.

Esanders renamed this task from VisualEditor can break line before a space to Link cartouches break word break algorithm.May 9 2016, 2:27 PM
Jdforrester-WMF renamed this task from Link cartouches break word break algorithm to Link cartouches interfere with browsers' word break algorithms.May 9 2016, 3:18 PM
Jdforrester-WMF triaged this task as Lowest priority.
Jdforrester-WMF set the point value for this task to 40.
Jdforrester-WMF moved this task from To Triage to Freezer on the VisualEditor board.

There may be no feasible fix for this.

The cause is that the browser marks a break opportunity on either side of each img, as if it were a U+FFFC character (See http://www.unicode.org/reports/tr14/ at Contingent Break Opportunity).

The only way I can see to override this is to use tricks like wrapping each img in a styled inline annotation e.g. <span style='white-space: nowrap'>...</span> . (Actually that doesn't work properly in Chromium: it only works with a real U+FFFC and not with an img).

Since an img.ve-ce-nail element is used to force the cursor to a specific side of an inline annotation (namely the <a...>...</a>), putting it inside an annotation that the cursor can potentially expand is ... problematic. (And wrapping in a ce=false span triggers some nasty Chromium bugs, e.g. https://bugs.chromium.org/p/chromium/issues/detail?id=605418 ).

@dchan Have you tried using U+200D ZERO WIDTH JOINER to weld the <img> (aka U+FFFC) to the link?
(see https://eev.ee/blog/2015/09/12/dark-corners-of-unicode/ )

@dchan Have you tried using U+200D ZERO WIDTH JOINER to weld the <img> (aka U+FFFC) to the link?
(see https://eev.ee/blog/2015/09/12/dark-corners-of-unicode/ )

I tested this very briefly (code below) and it did not seem to help (tried with Chrome).

/**
 * @inheritdoc
 */
ve.ce.LinkAnnotation.prototype.attachContents = function () {
	var anchor = this.$anchor[ 0 ];
	// Insert post-open nail, annotation contents, and pre-close nail into the anchor
	anchor.appendChild( document.createTextNode( '\u200d' ) );
	anchor.appendChild( this.constructor.static.makeNail( 'post-open' ) );
	anchor.appendChild( document.createTextNode( '\u200d' ) );
	anchor.appendChild( this.contentFragment );
	anchor.appendChild( document.createTextNode( '\u200d' ) );
	anchor.appendChild( this.constructor.static.makeNail( 'pre-close' ) );
	anchor.appendChild( document.createTextNode( '\u200d' ) );
};

/**
 * @inheritdoc
 */
ve.ce.LinkAnnotation.prototype.appendTo = function ( node ) {
	// Insert pre-open nail, anchor, and post-close nail into a parent node
	node.appendChild( document.createTextNode( '\u200d' ) );
	node.appendChild( this.constructor.static.makeNail( 'pre-open' ) );
	node.appendChild( document.createTextNode( '\u200d' ) );
	node.appendChild( this.$anchor[ 0 ] );
	node.appendChild( document.createTextNode( '\u200d' ) );
	node.appendChild( this.constructor.static.makeNail( 'post-close' ) );
	node.appendChild( document.createTextNode( '\u200d' ) );
};