User:MusikAnimal/dablinkwarn.js

From Wikipedia, the free encyclopedia
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
(function (mw, $) {
    var $textarea = $('#wpTextbox1'),
        $editor = $textarea,
        api = new mw.Api();

    function addKeyListener() {
        $editor.off('keyup.dablinkwarn').on('keyup.dablinkwarn', function (e) {
            if (e.key === ']') {
                var cursorPosition = e.target.selectionStart,
                    context = $textarea.val().substring(0, cursorPosition),
                    matches = /.*(\[\[(.*?)(?:\|.*?]]|]]))$/.exec(context);

                if (matches && matches.length) {
                    // We always want the last match.
                    var pageTitle = matches[matches.length - 1].trim(),
                        // Also keep track of the start of the link so we can do replacements later.
                        linkWikitext = matches[matches.length - 2];
                    var linkPosition = context.length - linkWikitext.length;

                    api.get({
                        action: 'query',
                        titles: pageTitle,
                        prop: 'pageprops',
                        ppprop: 'disambiguation',
                        list: 'prefixsearch',
                        pssearch: pageTitle,
                        pslimit: 5,
                        formatversion: 2,
                    }).then(function (resp) {
                        if (resp.query.pages && resp.query.pages[0].pageprops
                            && resp.query.pages[0].pageprops.disambiguation === ''
                        ) {
                            var alternatives = resp.query.prefixsearch.map(function (elem) {
                                    return elem.title;
                                }).filter(function (title) {
                                    return title !== pageTitle;
                                }),
                                $container = $('<div>'),
                                $helpLink = $('<a>').prop('href', new mw.Title('Disambiguation', 4).getUrl())
                                    .prop('target', '_blank')
                                    .text('disambiguation page'),
                                $pageLink = $('<a>').prop('href', new mw.Title(pageTitle).getUrl())
                                    .prop('target', '_blank')
                                    .text(pageTitle),
                                $message = $('<p>').append('You linked to the page "')
                                    .append($pageLink)
                                    .append('" which is a ')
                                    .append($helpLink)
                                    .append('. ');
                            $container.append($message);

                            if (alternatives.length) {
                                $message.append('Did you mean one of the following?');
                                var $links = alternatives.map(function (title) {
                                        return $('<a>').prop('href', new mw.Title(title).getUrl())
                                            .prop('target', '_blank')
                                            .text(title);
                                    }),
                                    $altList = $('<ul>');
                                $links.forEach($link => {
                                    $altList.append(
                                        $('<li>').append($link)
                                    );
                                    $link.one('click', function (e) {
                                        if ($textarea.val().substring(linkPosition, linkPosition + linkWikitext.length) === linkWikitext) {
                                            e.preventDefault();
                                            var newLinkWikitext = linkWikitext.replace(/(\[\[.*?(\|.*?]]|]]))/, '[[' + $link.text() + '$2');
                                            $textarea.val(
                                                $textarea.val().substring(0, linkPosition)
                                                + newLinkWikitext
                                                + $textarea.val().substring(linkPosition + linkWikitext.length)
                                            );
                                            $(e.target).parents('.mw-notification').trigger('click');
                                        }
                                    });
                                });
                                $container.append($altList);
                            }

                            mw.notify($container, {
                                autoHideSeconds: 'long',
                                type: 'warn',
                            });
                        }
                    });
                }
            }
        });
    }

    function addListeners() {
        mw.hook('ext.CodeMirror.switch').add(function (_enabled, $target) {
            $editor.off('keyup.dablinkwarn');
            $editor = $target;
            addKeyListener();
        });
        addKeyListener();
    }

    // TODO: Only do this for inexperienced editors
    // TODO: Only target the mainspace (userspace enabled for safer testing purposes)
    // TODO: Only for desktop?
    if ([0, 2].includes(mw.config.get('wgNamespaceNumber'))
        && ['edit', 'submit'].includes(mw.config.get('wgAction'))
    ) {
        addListeners();
    }
})(mediaWiki, jQuery);