Jump to content

User:MusikAnimal/dablinkwarn.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
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);