跳转到内容

User:1F616EMO/NotabilitySearchRedo/core.js

维基百科,自由的百科全书
注意:保存之后,你必须清除浏览器缓存才能看到做出的更改。Google ChromeFirefoxMicrosoft EdgeSafari:按住⇧ Shift键并单击工具栏的“刷新”按钮。参阅Help:绕过浏览器缓存以获取更多帮助。
/*
 * Smarter notability search assistant (Chinese Wikipedia) v2.0
 * 
 * Use the following line to load this script:
 * mw.loader.load( "https://zh.wikipedia.org/w/index.php?title=User:1F616EMO/NotabilitySearchRedo/core.js&action=raw&ctype=text/javascript" );
 * 
 * This script is made by 1F616EMO on zhwiki, licensed under CC BY-SA 4.0.
 */
// <nowiki>

mw.loader.using([
    'mediawiki.api',
    'mediawiki.jqueryMsg',
    'ext.gadget.HanAssist',
]).then((require) => {
    window.NotabilitySearch = window.NotabilitySearch || {};
    window.NotabilitySearch.version = window.NotabilitySearch.version || '2.0';

    const api = new mw.Api();
    const { batchConv } = require('ext.gadget.HanAssist');

    mw.messages.set(batchConv({
        'notability-searchbox-close': {
            hans: '关闭',
            hant: '關閉',
        },
        'notability-searchbox-title': {
            hans: '检查条目是否符合收录标准',
            hant: '檢查條目是否符合收錄標準',
        },
        'notability-searchbox-section-titles-title': {
            hans: '条目标题',
            hant: '條目標題',
        },
        'notability-searchbox-section-categories-title': {
            hans: '条目分类',
            hant: '條目分類',
        },
        'notability-searchbox-section-hiddencats-title': {
            hans: '条目隐藏分类',
            hant: '條目隱藏分類',
        },
        'notability-searchbox-section-utilities-title': {
            hans: '搜寻工具',
            hant: '搜尋工具',
        },
        'notability-searchbox-submit': {
            hans: '搜索',
            hant: '搜尋',
        },

        'notability-searchbox-twaction-notability': {
            hans: '不符合收录标准',
            hant: '不符合收錄標準',
        },
        'notability-searchbox-twaction-notability-unreferenced': {
            hans: '收录标准无来源',
            hant: '收錄標準無來源',
        },
        'notability-searchbox-twaction-notability-xfd': {
            hans: '收录标准提删',
            hant: '收錄標準提刪',
        },

        'notability-searchbox-portlet-text': {
            hans: '收录标准搜寻',
            hant: '收錄標準搜尋',
        },
        'notability-searchbox-portlet-description': {
            hans: '从条目标题和分类构建搜索关键字',
            hant: '從條目標題和分類構建搜尋關鍵字',
        },
        'notability-searchbox-button': {
            hans: '高级收录标准搜索',
            hant: '進階收錄標準搜尋',
        },
    }));

    // See mediawiki/includes/parser/Parser.php:4751
    const tc = '.'; // Over simplified but works cuz Mediawiki already denied illegal ones

    const titleRegexes = [
        new RegExp(`^(${tc}+?)( ?\\(${tc}+\\))$`),                   // $p1
        new RegExp(`^(${tc}+?)( ?(${tc}+))$`),                      // $p2
        new RegExp(`^(${tc}+?)( ?\\(${tc}+\\)|)((?:, |,|، )${tc}+|)$`), // $p3
    ];

    const ContentLineRegex = /^(?!{{| *\|).*$/gm;
    const langRegex = /{{[Ll]ang(?:-|x\|)[a-z]{2,}\|([^|}]*?)(?:\|[^}]*?)?}}/g;

    function getTitles(titles) {
        const pagename = mw.config.get("wgPageName");
        titles.add(pagename.replace('_', ' '));
        const title = mw.config.get("wgTitle");
        titles.add(title);

        const nameparts = title.split('/');
        const subname = nameparts[nameparts.length - 1];
        titles.add(subname);

        // Extract capture group 1 from each of p1,4,3
        for (let i = 0; i < titleRegexes.length; i++) {
            const regex = titleRegexes[i];
            const matches = title.match(regex);
            if (matches && matches[1]) {
                titles.add(matches[1]);
            }
        }

        // Here comes the async part
        // fetch possible title form {{lang-xx|text|<other arguments...>}} and {{langx|xx|text|<other arguments...>}}

        return api.get({
            action: 'parse',
            prop: 'wikitext',
            page: pagename,
            section: 0,
        }).done((data) => {
            const wikitext = data.parse.wikitext['*'];
            const nonTemplateLineMatches = wikitext.match(ContentLineRegex);
            if (nonTemplateLineMatches) {
                for (let i = 0; i < nonTemplateLineMatches.length; i++) {
                    const line = nonTemplateLineMatches[i];
                    while (matches = langRegex.exec(line)) {
                        titles.add(matches[1]);
                    }
                }
            }
        });
    }

    function getCategories(categories, hiddencats) {
        return api.get({
            action: 'query',
            prop: 'categories',
            titles: mw.config.get('wgPageName'),
            clprop: 'hidden',
            cllimit: 'max',
            formatversion: 2,
        }).done((data) => {
            const page = data.query.pages[0];
            if (page && page.categories) {
                for (let i = 0; i < page.categories.length; i++) {
                    const catname = page.categories[i].title.replace(/^Category:/, '');
                    if (page.categories[i].hidden) {
                        hiddencats.add(catname);
                    } else {
                        categories.add(catname);
                    }
                }
            }
        });
    }

    window.NotabilitySearch.searchUtilityFunctions = window.NotabilitySearch.searchUtilityFunctions || [];
    function getSearchUtilities(searchUtilities, titles, categories, hiddencats) {
        const promises = [];

        for (const func of window.NotabilitySearch.searchUtilityFunctions) {
            if (typeof func === 'function') {
                const result = func(searchUtilities, titles, categories, hiddencats);
                if (result && result.then) {
                    promises.push(result);
                }
            } else {
                searchUtilities.add(func);
            }
        }

        return Promise.all(promises);
    }

    // {Display text, function on click}
    window.NotabilitySearch.buttonUtilitiesFunctions = window.NotabilitySearch.buttonUtilitiesFunctions || [];
    function getButtonUtilities($actionlist) {
        const promises = [];
        const addButtonUtility = (data) => {
            if (typeof data[0] == 'object') {
                // Hmm, nested
                for (const item of data) {
                    addButtonUtility(item);
                }
                return;
            }
            const [text, func] = data;
            $("<button>")
                .attr('aria-label', text)
                .attr('title', text)
                .text(text)
                .on('click', func)
                .appendTo($actionlist);
        }
        for (const func of window.NotabilitySearch.buttonUtilitiesFunctions) {
            if (typeof func === 'function') {
                const result = func(addButtonUtility);
                if (result && result.then) {
                    promises.push(result.then((data) => addButtonUtility(data)));
                } else if (result) {
                    addButtonUtility(result);
                }
            } else {
                addButtonUtility(func);
            }
        }
        return Promise.all(promises);
    }

    window.NotabilitySearch.createNotabilitySearchBox = function () {
        if ($('#notability-searchbox').length) return;

        const titles = new Set();
        const categories = new Set();
        const hiddencats = new Set();
        const searchUtilities = new Set();
        const $actionlist = $('<div class="notability-searchbox-twaction-list">');

        Promise.all([
            getTitles(titles),
            getCategories(categories, hiddencats),
            getButtonUtilities($actionlist),
        ]).then(() => {
            return getSearchUtilities(searchUtilities, titles, categories, hiddencats);
        }).then(() => {
            const $searchbox = $('<div id="notability-searchbox" class="notability-searchbox skin-invert">');

            $('<button class="notability-searchbox-close">')
                .attr('aria-label', mw.message('notability-searchbox-close').text())
                .attr('title', mw.message('notability-searchbox-close').text())
                .html('&times;')
                .on('click', () => {
                    $searchbox.remove();
                })
                .appendTo($searchbox);

            $('<div class="notability-searchbox-title">')
                .text(mw.message('notability-searchbox-title').text())
                .appendTo($searchbox);

            const $section_titles = $('<div class="notability-searchbox-section" id="notability-searchbox-section-titles">')
                .appendTo($searchbox);
            $('<div class="notability-searchbox-section-title">')
                .text(mw.message('notability-searchbox-section-titles-title').text())
                .appendTo($section_titles);
            const $section_titles_content = $('<ul class="notability-searchbox-section-content">')
                .appendTo($section_titles);
            for (const title of titles) {
                $('<li>')
                    .html($('<bdi>').html($('<a>')
                        .attr('href', 'javascript:addNotabilityQuery("' + title + '")')
                        .text(title)))
                    .appendTo($section_titles_content);
            }

            const $section_categories = $('<div class="notability-searchbox-section" id="notability-searchbox-section-categories">')
                .appendTo($searchbox);
            $('<div class="notability-searchbox-section-title">')
                .text(mw.message('notability-searchbox-section-categories-title').text())
                .appendTo($section_categories);
            const $section_categories_content = $('<ul class="notability-searchbox-section-content">')
                .appendTo($section_categories);
            for (category of categories) {
                $('<li>')
                    .html($('<bdi>').html($('<a>')
                        .attr('href', 'javascript:addNotabilityQuery("' + category + '")')
                        .text(category)))
                    .appendTo($section_categories_content);
            }

            const $section_hiddencats = $('<div class="notability-searchbox-section" id="notability-searchbox-section-hiddencats">')
                .appendTo($searchbox);
            $('<div class="notability-searchbox-section-title">')
                .text(mw.message('notability-searchbox-section-hiddencats-title').text())
                .appendTo($section_hiddencats);
            const $section_hiddencats_content = $('<ul class="notability-searchbox-section-content">')
                .appendTo($section_hiddencats);
            for (hiddencat of hiddencats) {
                $('<li>')
                    .html($('<bdi>').html($('<a>')
                        .attr('href', 'javascript:addNotabilityQuery("' + hiddencat + '")')
                        .text(hiddencat)))
                    .appendTo($section_hiddencats_content);
            }

            const $section_utilities = $('<div class="notability-searchbox-section" id="notability-searchbox-section-utilities">')
                .appendTo($searchbox);
            $('<div class="notability-searchbox-section-title">')
                .text(mw.message('notability-searchbox-section-utilities-title').text())
                .appendTo($section_utilities);
            const $section_utilities_content = $('<ul class="notability-searchbox-section-content">')
                .appendTo($section_utilities);
            for (utility of searchUtilities) {
                $('<li>')
                    .html($('<bdi>').html($('<a>')
                        .attr('href', 'javascript:addNotabilityQuery("' + utility + '")')
                        .text(utility)))
                    .appendTo($section_utilities_content);
            }

            const $searchform = $('<form class="notability-searchbox-form">')
                .attr('action', 'https://www.google.com/search')
                .attr('autocomplete', 'off')
                .attr('method', 'get')
                .attr('role', 'search')
                .attr('target', '_blank')
                .appendTo($searchbox);
            $('<input type="text" class="notability-searchbox-input">')
                .attr('name', 'q')
                .attr('placeholder', mw.message('notability-searchbox-input-placeholder').text())
                .val('-wikipedia ')
                .appendTo($searchform);
            $('<input type="submit" class="notability-searchbox-submit">')
                .attr('aria-label', mw.message('notability-searchbox-submit').text())
                .attr('title', mw.message('notability-searchbox-submit').text())
                .val(mw.message('notability-searchbox-submit').text())
                .appendTo($searchform);

            $actionlist.appendTo($searchbox);

            $('<div style="clear:both">')
                .appendTo($searchform);

            $searchbox.insertBefore('#mw-content-text');
            $('#notability-searchbox .notability-searchbox-form input[name="q"]').focus();
        });
    }

    window.addNotabilityQuery = function (query) {
        const $input = $('#notability-searchbox .notability-searchbox-form input[name="q"]');
        const currentValue = $input.val() ?? '';
        $input.val(currentValue + query + ' ');
        $input.focus();
    };

    mw.loader.load('//zh.wikipedia.org/w/index.php?title=User:1F616EMO/NotabilitySearchRedo/core.css&action=raw&ctype=text/css', 'text/css');

    // Add portlet link

    $(mw.util.addPortletLink(
        $("#p-cactions").length ? 'p-cactions' : 'p-tb', '#',
        mw.message('notability-searchbox-portlet-text').text(), 'notability-searchbox-portlet',
        mw.message('notability-searchbox-portlet-description').text(), '1'))
        .click((e) => {
            e.preventDefault();

            window.NotabilitySearch.createNotabilitySearchBox();
        });

    // Add into notability template

    $(".box-Notability .mbox-text-span").append($('<a class="notability-searchbox-button hide-when-compact">')
        .text(mw.message('notability-searchbox-button').text())
        .attr('title', mw.message('notability-searchbox-button').text())
        .attr('aria-label', mw.message('notability-searchbox-button').text())
        .click((e) => {
            e.preventDefault();
            $(".overlay-issues button.cancel").click();
            window.NotabilitySearch.createNotabilitySearchBox();
        })
    );

    // zhwiki custom
    window.NotabilitySearch.buttonUtilitiesFunctions.push(() => {
        const utilities = [];
        if (window.Twinkle) {
            utilities.push([
                mw.message('notability-searchbox-twaction-notability').text(),
                (e) => {
                    e.preventDefault();

                    $("#friendly-tag a").first().click(); // Tag window
                    $(`.morebits-dialog-content input[value="Notability"]:not(:checked)`).click();
                },
            ]);
            utilities.push([
                mw.message('notability-searchbox-twaction-notability-unreferenced').text(),
                (e) => {
                    e.preventDefault();

                    $("#friendly-tag a").first().click(); // Tag window
                    $(`.morebits-dialog-content input[value="Notability Unreferenced"]:not(:checked)`).click();
                },
            ]);
            utilities.push([
                mw.message('notability-searchbox-twaction-notability-xfd').text(),
                (e) => {
                    e.preventDefault();

                    $("#tw-xfd a").first().click(); // XFD window
                    const $xfdcat = $('.morebits-dialog-content select[name="xfdcat"]')
                        .val('fame');
                    Twinkle.xfd.callback.change_afd_category({
                        target: $xfdcat[0],
                    });
                },
            ]);
        }

        if (($m2dButton = $("#ca-m2d")).length) {
            // Move to draft
            utilities.push([
                $m2dButton.find("a span").text(),
                (e) => {
                    e.preventDefault();

                    $m2dButton.click();
                }
            ]);
        }

        return utilities;
    });
});