MediaWiki:Common.js

Матеріал з Київський національний лінгвістичний університет
Перейти до навігації Перейти до пошуку

Увага: Після публікування слід очистити кеш браузера, щоб побачити зміни.

  • Firefox / Safari: тримайте Shift, коли натискаєте Оновити, або натисніть Ctrl-F5 чи Ctrl-Shift-R (⌘-R на Apple Mac)
  • Google Chrome: натисніть Ctrl-Shift-R (⌘-Shift-R на Apple Mac)
  • Edge: тримайте Ctrl, коли натискаєте Оновити, або натисніть Ctrl-F5.
// Виправляємо viewport
(function() {
    var viewport = document.querySelector('meta[name="viewport"]');
    if (viewport) {
        viewport.setAttribute('content', 'width=device-width, initial-scale=1.0');
    } else {
        var meta = document.createElement('meta');
        meta.name = 'viewport';
        meta.content = 'width=device-width, initial-scale=1.0';
        document.head.appendChild(meta);
    }
})();

$(function() {
    $('.category-card').each(function() {
        var $card = $(this);
        var href = $card.attr('data-href');
        
        if (href) {
            $card.css('cursor', 'pointer');
            
            $card.on('click', function(e) {
                if ($(e.target).closest('a').length === 0) {
                    window.location.href = href;
                }
            });
            
            $card.hover(
                function() { $card.addClass('card-hover'); },
                function() { $card.removeClass('card-hover'); }
            );
        }
    });
});

/* ══════════════════════════════════════════════
   ВИПАДКОВІ СТАТТІ (FIX)
══════════════════════════════════════════════ */

function loadRandomArticles() {
    var list = document.getElementById('random-articles-list');
    if (!list) return;

    list.innerHTML = '<div class="random-articles-loading">Завантаження...</div>';

    var apiBase = mw.config.get('wgScriptPath') + '/api.php';
    var excludedPages = ['Головна сторінка', 'Структурні підрозділи', 'Викладачі'];

    fetch(apiBase + '?action=query&list=random&rnnamespace=0&rnlimit=10&format=json')
        .then(function (r) { return r.json(); })
        .then(function (data) {

            if (!data.query || !data.query.random) {
                throw new Error('Random API error');
            }

            var pages = data.query.random
                .filter(function (p) { return excludedPages.indexOf(p.title) === -1; })
                .slice(0, 3);

            var titles = pages.map(function (p) { return p.title; }).join('|');

            return fetch(
                apiBase + '?action=query' +
                '&titles=' + encodeURIComponent(titles) +
                '&prop=revisions&rvslots=main&rvprop=content&format=json'
            );
        })
        .then(function (r) { return r.json(); })
        .then(function (data) {

            var pages = Object.values((data.query && data.query.pages) || {});
            list.innerHTML = '';

            var promises = pages.map(function (page) {

                var title   = page.title;
                var pageUrl = mw.config.get('wgArticlePath').replace(
                    '$1', encodeURIComponent(title.replace(/ /g, '_'))
                );

                var content = '';
                if (page.revisions &&
                    page.revisions[0] &&
                    page.revisions[0].slots &&
                    page.revisions[0].slots.main) {
                    content = page.revisions[0].slots.main['*'] || '';
                }

                var excerpt = extractDescription(content) || 'Немає опису.';
                var imgName = extractImageName(content);

                if (imgName) {
                    var fileTitle = /^(Файл|File|Image|Зображення):/i.test(imgName)
                        ? imgName : 'File:' + imgName;

                    return fetch(
                        apiBase + '?action=query' +
                        '&titles=' + encodeURIComponent(fileTitle) +
                        '&prop=imageinfo&iiprop=url&iiurlwidth=120&format=json'
                    )
                    .then(function (r) { return r.json(); })
                    .then(function (imgData) {
                        var ip = Object.values(imgData.query.pages);
                        var ii = ip[0] && ip[0].imageinfo && ip[0].imageinfo[0];
                        return {
                            title: title,
                            excerpt: excerpt,
                            pageUrl: pageUrl,
                            imgSrc: ii ? (ii.thumburl || ii.url) : null
                        };
                    })
                    .catch(function () {
                        return { title: title, excerpt: excerpt, pageUrl: pageUrl, imgSrc: null };
                    });
                }

                return Promise.resolve({
                    title: title,
                    excerpt: excerpt,
                    pageUrl: pageUrl,
                    imgSrc: null
                });
            });

            return Promise.all(promises);
        })
        .then(function (results) {
            var el = document.getElementById('random-articles-list');
            if (!el) return;

            el.innerHTML = '';

            results.forEach(function (item) {
                var thumbHtml = item.imgSrc
                    ? '<img class="random-article-thumb" src="' + item.imgSrc + '" alt="">'
                    : '<div class="random-article-thumb-placeholder">📄</div>';

                var card = document.createElement('a');
                card.href      = item.pageUrl;
                card.className = 'random-article-card';
                card.innerHTML =
                    thumbHtml +
                    '<div class="random-article-info">' +
                        '<div class="random-article-title">'  + mw.html.escape(item.title)  + '</div>' +
                        '<div class="random-article-excerpt">' + mw.html.escape(item.excerpt) + '</div>' +
                    '</div>';

                el.appendChild(card);
            });
        })
        .catch(function (err) {
            console.error('[RA]', err);
            list.innerHTML = '<div class="random-articles-loading">Не вдалося завантажити статті.</div>';
        });
}

mw.hook('wikipage.content').add(function () {
    var panel = document.getElementById('random-articles-panel');
    if (!panel) return;

    loadRandomArticles();

    var btn = document.getElementById('random-articles-refresh');
    if (btn) btn.addEventListener('click', loadRandomArticles);
});

/* ─────────────────────────────────────────────
   ПАРСЕРИ
──────────────────────────────────────────── */

function extractImageName(wikitext) {
    if (!wikitext) return null;

    var m = wikitext.match(/\|\s*image\s*=\s*([^\|\n\}]+)/i);
    if (m && m[1].trim()) return m[1].trim();

    m = wikitext.match(/\[\[(?:Файл|File|Зображення|Image):([^\|\]]+)/i);
    return m ? m[1].trim() : null;
}

function extractDescription(wikitext) {
    if (!wikitext) return '';

    var text = wikitext
        .replace(/\{\{[\s\S]*?\}\}/g, '')
        .replace(/\[\[(?:[^\|\]]*\|)?([^\]]+)\]\]/g, '$1')
        .replace(/'{2,3}/g, '')
        .replace(/<[^>]+>/g, '');

    var lines = text.split('\n')
        .map(function (l) { return l.trim(); })
        .filter(function (l) { return l.length > 20; });

    if (!lines.length) return '';

    var result = lines[0].substring(0, 180);
    return lines[0].length > 180 ? result + '…' : result;
}