Nc4lsD09 / wikipedia_add_desc

// ==UserScript==
// @name         wikipedia_add_desc
// @namespace    https://catherine.v0cyc1pp.com/
// @version      1.3
// @license      GPL-3.0-or-later
// @description  Wikipediaタイトル下にWikidataの簡易説明を表示
// @author       greg10
// @match        https://*.wikipedia.org/wiki/*
// @exclude      https://ja.wikipedia.org/wiki/%E5%88%A9%E7%94%A8%E8%80%85:* // 利用者:
// @exclude      https://ja.wikipedia.org/wiki/*:*
// @run-at       document-idle
// @grant        none
// ==/UserScript==

(function () {
    "use strict";

    // タイトル要素取得
    const title = document.querySelector("#firstHeading");
    if (!title) return;

    // タイトル+説明を入れる縦コンテナ
    const wrapper = document.createElement("div");

    wrapper.style.display = "flex";
    wrapper.style.flexDirection = "column";
    wrapper.style.alignItems = "flex-start";
    wrapper.style.width = "100%";

    // h1 を wrapper に移動
    title.parentNode.insertBefore(wrapper, title);
    wrapper.appendChild(title);

    // 表示用要素を先に作成
    const box = document.createElement("div");

    box.textContent = "(Wikidataから説明を取得中...)";

    box.style.fontSize = "0.95em";
    box.style.color = "#666";
    box.style.marginTop = "0.1em";
    box.style.marginBottom = "0.1em";
    //box.style.display = 'block';
    //box.style.clear = 'both';
    //box.style.fontStyle = 'italic';

    // タイトル下へ追加
    const parent = title.parentElement || title;
    //parent.insertBefore(box, title.nextSibling);
    wrapper.appendChild(box);

    // 言語取得
    const lang = location.hostname.split(".")[0];

    /*
    // ページタイトル取得
    const pageTitle = mw.config.get("wgTitle");
    if (!pageTitle) {
        box.textContent = "ページタイトル取得失敗";
        return;
    }
    */
    // ページタイトル取得
    const pageTitle = decodeURIComponent(
        location.pathname.replace(/^\/wiki\//, ""),
    ).replace(/_/g, " ");

    if (!pageTitle) {
        box.textContent = "ページタイトル取得失敗";
        return;
    }

    // Wikipedia API
    const apiUrl =
        `https://${lang}.wikipedia.org/w/api.php` +
        `?action=query` +
        `&prop=pageprops` +
        `&titles=${encodeURIComponent(pageTitle)}` +
        `&format=json` +
        `&origin=*`;

    fetch(apiUrl)
        .then((res) => res.json())
        .then((data) => {
            const pages = data.query.pages;
            const page = Object.values(pages)[0];

            if (!page.pageprops || !page.pageprops.wikibase_item) {
                box.textContent = "Wikidata項目なし";
                return;
            }

            const wikidataId = page.pageprops.wikibase_item;

            // Wikidata API
            const wdUrl = `https://www.wikidata.org/wiki/Special:EntityData/${wikidataId}.json`;

            return fetch(wdUrl)
                .then((res) => res.json())
                .then((wd) => {
                    const entity = wd.entities[wikidataId];

                    if (!entity || !entity.descriptions) {
                        box.textContent = "説明なし";
                        return;
                    }

                    // 日本語優先
                    const desc =
                        entity.descriptions.ja?.value ||
                        entity.descriptions[lang]?.value ||
                        entity.descriptions.en?.value;

                    if (!desc) {
                        box.textContent = "説明なし";
                        return;
                    }

                    // 説明表示
                    box.textContent = desc;
                });
        })
        .catch((err) => {
            console.error(err);
            box.textContent = "取得失敗";
        });
})();