1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
/*!
* VisualEditor UserInterface MWInternalLinkAnnotationWidget class.
*
* @copyright See AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
/**
* Creates an ve.ui.MWInternalLinkAnnotationWidget object.
*
* @class
* @extends ve.ui.LinkAnnotationWidget
*
* @constructor
* @param {Object} [config] Configuration options
*/
ve.ui.MWInternalLinkAnnotationWidget = function VeUiMWInternalLinkAnnotationWidget() {
// Parent constructor
ve.ui.MWInternalLinkAnnotationWidget.super.apply( this, arguments );
};
/* Inheritance */
OO.inheritClass( ve.ui.MWInternalLinkAnnotationWidget, ve.ui.LinkAnnotationWidget );
/* Static Methods */
/**
* @inheritdoc
*/
ve.ui.MWInternalLinkAnnotationWidget.static.getAnnotationFromText = function ( value ) {
const trimmed = value.trim(),
title = mw.Title.newFromText( trimmed );
if ( !title ) {
return null;
}
return ve.dm.MWInternalLinkAnnotation.static.newFromTitle( title );
};
/**
* @inheritdoc
*/
ve.ui.MWInternalLinkAnnotationWidget.static.getTextFromAnnotation = function ( annotation ) {
return annotation ? annotation.getAttribute( 'normalizedTitle' ) : '';
};
/* Methods */
/**
* Create a text input widget to be used by the annotation widget
*
* @param {Object} [config] Configuration options
* @return {OO.ui.TextInputWidget} Text input widget
*/
ve.ui.MWInternalLinkAnnotationWidget.prototype.createInputWidget = function ( config ) {
const input = new mw.widgets.TitleSearchWidget( ve.extendObject( {
icon: 'search',
excludeCurrentPage: true,
showImages: mw.config.get( 'wgVisualEditorConfig' ).usePageImages,
showDescriptions: mw.config.get( 'wgVisualEditorConfig' ).usePageDescriptions,
showDisambigsLast: true,
showInterwikis: true,
searchFragments: true,
addQueryInput: false,
api: ve.init.target.getContentApi(),
cache: ve.init.platform.linkCache
}, config ) );
// Put query first in DOM
// TODO: Consider upstreaming this to SearchWidget
input.$element.prepend( input.$query );
// Remove 'maxlength', because it should not apply to full URLs, which we allow users to paste
// here. Maximum length of page titles will still be enforced by JS validation later (we can't
// override maxLength config option, because that would break the validation).
input.getQuery().$input.removeAttr( 'maxlength' );
input.query.$input.attr( 'aria-label', mw.msg( 'visualeditor-linkinspector-button-link-internal' ) );
return input;
};
/**
* @inheritdoc
*/
ve.ui.MWInternalLinkAnnotationWidget.prototype.getTextInputWidget = function () {
return this.input.query;
};
// #getHref returns the link title, not a fully resolved URL, however the only
// use case of widget.getHref is for link insertion text, which expects a title.
//
// Callers needing the full resolved URL should use ve.resolveUrl
/**
* @inheritdoc
*/
ve.ui.MWInternalLinkAnnotationWidget.prototype.onTextChange = function ( value ) {
const htmlDoc = this.getElementDocument(),
namespacesWithSubpages = mw.config.get( 'wgVisualEditorConfig' ).namespacesWithSubpages,
basePageObj = mw.Title.newFromText( mw.config.get( 'wgRelevantPageName' ) );
// Specific thing we want to check: has a valid URL for an internal page
// been pasted into here, in which case we want to convert it to just the
// page title. This has to happen /here/ because a URL can reference a
// valid page while not being a valid Title (e.g. if it contains a "%").
if ( ve.init.platform.getExternalLinkUrlProtocolsRegExp().test( value ) ) {
const targetData = mw.libs.ve.getTargetDataFromHref(
value,
htmlDoc
);
if ( targetData.isInternal ) {
value = targetData.title;
this.input.query.setValue( targetData.title );
}
} else if ( namespacesWithSubpages.indexOf( basePageObj.namespace ) !== -1 && value[ 0 ] === '/' ) {
// This does make it more-difficult to deliberately link to a page in the
// default namespace that starts with a / when you're on a subpage-allowing
// namespace. However, the exact same trick you need to know to make it work
// in plain wikitext applies: search for `:/foo`.
value = basePageObj.getPrefixedText() + value;
this.input.query.setValue( value );
}
return ve.ui.MWInternalLinkAnnotationWidget.super.prototype.onTextChange.call( this, value );
};
|