User:Anne drew/Veracity.js

☆ Save On Wikipedia ↗
// [[Category:Wikipedia scripts]]
// <nowiki>
(function () {
    'use strict';

    /******************************************************************************
    Copyright (c) Microsoft Corporation.

    Permission to use, copy, modify, and/or distribute this software for any
    purpose with or without fee is hereby granted.

    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
    REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
    AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
    INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
    LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
    OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
    PERFORMANCE OF THIS SOFTWARE.
    ***************************************************************************** */
    /* global Reflect, Promise, SuppressedError, Symbol, Iterator */


    function __awaiter(thisArg, _arguments, P, generator) {
        function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
        return new (P || (P = Promise))(function (resolve, reject) {
            function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
            function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
            function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
            step((generator = generator.apply(thisArg, _arguments || [])).next());
        });
    }

    function __generator(thisArg, body) {
        var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
        return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
        function verb(n) { return function (v) { return step([n, v]); }; }
        function step(op) {
            if (f) throw new TypeError("Generator is already executing.");
            while (g && (g = 0, op[0] && (_ = 0)), _) try {
                if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
                if (y = 0, t) op = [op[0] & 2, t.value];
                switch (op[0]) {
                    case 0: case 1: t = op; break;
                    case 4: _.label++; return { value: op[1], done: false };
                    case 5: _.label++; y = op[1]; op = [0]; continue;
                    case 7: op = _.ops.pop(); _.trys.pop(); continue;
                    default:
                        if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
                        if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
                        if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
                        if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
                        if (t[2]) _.ops.pop();
                        _.trys.pop(); continue;
                }
                op = body.call(thisArg, _);
            } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
            if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
        }
    }

    typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
        var e = new Error(message);
        return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
    };

    function fetchArticleHtml(articleTitle) {
        return __awaiter(this, void 0, void 0, function () {
            var apiUrl, response, data, html_content, parser, revid, e_1;
            return __generator(this, function (_a) {
                switch (_a.label) {
                    case 0:
                        apiUrl = "/w/api.php?action=parse&page=".concat(encodeURIComponent(articleTitle), "&prop=text|revid&format=json&origin=*");
                        _a.label = 1;
                    case 1:
                        _a.trys.push([1, 4, , 5]);
                        return [4, fetch(apiUrl)];
                    case 2:
                        response = _a.sent();
                        return [4, response.json()];
                    case 3:
                        data = _a.sent();
                        if (data.error) {
                            throw new Error(data.error.info);
                        }
                        html_content = data.parse.text['*'];
                        parser = new DOMParser();
                        revid = data.parse.revid;
                        return [2, {
                                doc: parser.parseFromString(html_content, 'text/html'),
                                revid: revid,
                            }];
                    case 4:
                        e_1 = _a.sent();
                        console.error("Error fetching article: ".concat(e_1));
                        alert("Error fetching article: ".concat(e_1));
                        return [2, null];
                    case 5: return [2];
                }
            });
        });
    }

    function showInputDialog(defaultTitle) {
        if (defaultTitle === void 0) { defaultTitle = ""; }
        return new Promise(function (resolve, reject) {
            var escapedTitle = defaultTitle.replace(/"/g, "&quot;");
            var dialogHTML = "\n                <div id=\"ref-extractor-dialog\" style=\"position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: #ffffff; border-radius: 12px; padding: 32px; z-index: 10000; box-shadow: 0 8px 32px rgba(0,0,0,0.12), 0 2px 8px rgba(0,0,0,0.08); min-width: 400px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;\">\n                    <form id=\"ref-extractor-form\" style=\"display: flex; flex-direction: column; gap: 24px;\">\n                        <h3 style=\"margin: 0; font-size: 20px; font-weight: 600; color: #1a1a1a; letter-spacing: -0.01em;\">Create source verification table</h3>\n\n                        <div style=\"display: flex; flex-direction: column; gap: 16px;\">\n                            <div style=\"display: flex; flex-direction: column; gap: 8px;\">\n                                <label for=\"article-title\" style=\"font-size: 14px; font-weight: 500; color: #404040;\">Article name:</label>\n                                <input type=\"text\" id=\"article-title\" name=\"article-title\" value=\"".concat(escapedTitle, "\" style=\"width: 100%; padding: 8px 12px; border: 1.5px solid #d4d4d4; border-radius: 8px; font-size: 14px; box-sizing: border-box; transition: border-color 0.2s;\" required>\n                            </div>\n\n                            <div style=\"display: flex; flex-direction: column; gap: 8px;\">\n                                <div style=\"display: flex; align-items: center; justify-content: space-between;\">\n                                    <label for=\"sample-value\" style=\"font-size: 14px; font-weight: 500; color: #404040;\">Passages to check:</label>\n                                    <input type=\"number\" id=\"sample-value\" name=\"sample-value\" min=\"1\" style=\"width: 88px; padding: 8px 12px; border: 1.5px solid #d4d4d4; border-radius: 8px; font-size: 14px; box-sizing: border-box; transition: border-color 0.2s;\" placeholder=\"All\">\n                                </div>\n                                <div style=\"display: flex; gap: 16px; padding: 12px; background: #f0f0f0; border-radius: 8px; font-size: 13px; color: #666;\">\n                                    <label style=\"display: flex; align-items: center; gap: 8px; cursor: pointer;\">\n                                        <input type=\"radio\" name=\"sample-mode\" value=\"percent\" checked style=\"cursor: pointer;\">\n                                        <span>Percentage (%)</span>\n                                    </label>\n                                    <label style=\"display: flex; align-items: center; gap: 8px; cursor: pointer;\">\n                                        <input type=\"radio\" name=\"sample-mode\" value=\"count\" style=\"cursor: pointer;\">\n                                        <span>Exact count</span>\n                                    </label>\n                                </div>\n                            </div>\n\n                            <div style=\"display: flex; flex-direction: column; gap: 8px;\">\n                                <div style=\"display: flex; align-items: center; justify-content: space-between;\">\n                                    <label for=\"min-citations\" style=\"font-size: 14px; font-weight: 500; color: #404040;\">Min. citations per passage:</label>\n                                    <input type=\"number\" id=\"min-citations\" name=\"min-citations\" min=\"1\" value=\"1\" style=\"width: 88px; padding: 8px 12px; border: 1.5px solid #d4d4d4; border-radius: 8px; font-size: 14px; box-sizing: border-box; transition: border-color 0.2s;\">\n                                </div>\n                                <div style=\"font-size: 12px; color: #666;\">Set to 2+ to find passages with possible <a href=\"https://en.wikipedia.org/wiki/Wikipedia:Citation_overkill\" target=\"_blank\" style=\"color: #2563eb;\">WP:OVERCITE</a> or <a href=\"https://en.wikipedia.org/wiki/Wikipedia:No_original_research#Synthesis_of_published_material\" target=\"_blank\" style=\"color: #2563eb;\">WP:SYNTH</a> issues</div>\n                            </div>\n                        </div>\n\n                        <label style=\"display: flex; align-items: center; gap: 8px; cursor: pointer;\">\n                            <input type=\"checkbox\" id=\"use-sym\" name=\"use-sym\" style=\"cursor: pointer; width: 16px; height: 16px;\">\n                            <span style=\"font-size: 14px; color: #404040;\">Use Wikipedia icon templates (not recommended for FA reviews)</span>\n                        </label>\n\n                        <label style=\"display: flex; align-items: center; gap: 8px; cursor: pointer;\">\n                            <input type=\"checkbox\" id=\"expanded\" name=\"expanded\" style=\"cursor: pointer; width: 16px; height: 16px;\">\n                            <span style=\"font-size: 14px; color: #404040;\">Table initially expanded</span>\n                        </label>\n\n                        <label style=\"display: flex; align-items: center; gap: 8px; cursor: pointer;\">\n                            <input type=\"checkbox\" id=\"include-sections\" name=\"include-sections\" style=\"cursor: pointer; width: 16px; height: 16px;\">\n                            <span style=\"font-size: 14px; color: #404040;\">Include top-level headings in table</span>\n                        </label>\n\n                        <div style=\"display: flex; justify-content: flex-end; gap: 8px;\">\n                            <button type=\"button\" id=\"cancel-button\" style=\"padding: 8px 20px; border: 1.5px solid #d4d4d4; background: #ffffff; border-radius: 8px; font-size: 14px; font-weight: 500; color: #404040; cursor: pointer; transition: all 0.2s;\">Cancel</button>\n                            <button type=\"submit\" style=\"padding: 8px 20px; border: none; background: #2563eb; border-radius: 8px; font-size: 14px; font-weight: 500; color: #ffffff; cursor: pointer; transition: all 0.2s;\">Create table</button>\n                        </div>\n                    </form>\n                </div>\n                <div id=\"ref-extractor-overlay\" style=\"position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 9999;\"></div>\n            ");
            document.body.insertAdjacentHTML("beforeend", dialogHTML);
            var dialog = document.getElementById("ref-extractor-dialog");
            var overlay = document.getElementById("ref-extractor-overlay");
            var form = document.getElementById("ref-extractor-form");
            var cancelButton = document.getElementById("cancel-button");
            var closeDialog = function () {
                dialog === null || dialog === void 0 ? void 0 : dialog.remove();
                overlay === null || overlay === void 0 ? void 0 : overlay.remove();
            };
            form.addEventListener("submit", function (e) {
                var _a, _b, _c;
                e.preventDefault();
                var formData = new FormData(form);
                var articleTitle = formData.get("article-title");
                var sampleValue = formData.get("sample-value");
                var sampleModeInput = form.querySelector('input[name="sample-mode"]:checked');
                var sampleMode = (sampleModeInput === null || sampleModeInput === void 0 ? void 0 : sampleModeInput.value) || "percent";
                var useSym = ((_a = form.querySelector("#use-sym")) === null || _a === void 0 ? void 0 : _a.checked) || false;
                var expanded = ((_b = form.querySelector("#expanded")) === null || _b === void 0 ? void 0 : _b.checked) || false;
                var includeSectionHeadings = ((_c = form.querySelector("#include-sections")) === null || _c === void 0 ? void 0 : _c.checked) || false;
                var minCitations = formData.get("min-citations");
                closeDialog();
                resolve({
                    articleTitle: articleTitle,
                    sampleValue: sampleValue ? parseInt(sampleValue, 10) : null,
                    sampleMode: sampleMode,
                    useSym: useSym,
                    minCitations: minCitations ? parseInt(minCitations, 10) : 1,
                    collapsed: !expanded,
                    includeSectionHeadings: includeSectionHeadings,
                });
            });
            cancelButton === null || cancelButton === void 0 ? void 0 : cancelButton.addEventListener("click", function () {
                closeDialog();
                reject("Dialog canceled");
            });
            overlay === null || overlay === void 0 ? void 0 : overlay.addEventListener("click", function () {
                closeDialog();
                reject("Dialog canceled");
            });
        });
    }

    var ELEMENT_NODE = 1;
    var TEXT_NODE = 3;
    function stripHash(href) {
        return href ? href.replace(/^#/, '') : '';
    }
    function normalizeWhitespace(text) {
        return text.replace(/\s+/g, ' ').trim();
    }
    function parseCitationFromSup(sup) {
        var _a;
        var link = sup.querySelector('a');
        if (!link)
            return null;
        return {
            text: ((_a = link.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || '',
            href: stripHash(link.getAttribute('href')),
            cite_ref: sup.id || '',
        };
    }
    function findCurrentSection(element) {
        var _a, _b;
        var current = element;
        while (current) {
            var sibling = current.previousElementSibling;
            while (sibling) {
                if (sibling.matches('div.mw-heading.mw-heading2')) {
                    var h2 = sibling.querySelector('h2');
                    if (h2) {
                        return ((_a = h2.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || '';
                    }
                }
                if (sibling.matches('h2')) {
                    return ((_b = sibling.textContent) === null || _b === void 0 ? void 0 : _b.trim()) || '';
                }
                sibling = sibling.previousElementSibling;
            }
            current = current.parentElement;
            if (current === null || current === void 0 ? void 0 : current.matches('div.mw-parser-output, body')) {
                break;
            }
        }
        return '';
    }
    function extractArticleTextWithCitations(doc) {
        var content = doc.querySelector('div.mw-parser-output');
        if (!content)
            return [];
        var appearances = [];
        var global_group_id = 0;
        content.querySelectorAll('p, li, dd, dt, figcaption, .thumbcaption').forEach(function (element) {
            var _a;
            if (element.closest('table.infobox, table.wikitable')) {
                return;
            }
            var parentRefList = element.closest('ol.references');
            if (parentRefList && !parentRefList.hasAttribute('data-mw-group')) {
                return;
            }
            var section = findCurrentSection(element);
            var targetNode = element;
            if (parentRefList && parentRefList.hasAttribute('data-mw-group')) {
                var refTextSpan = element.querySelector('span.reference-text');
                if (refTextSpan) {
                    targetNode = refTextSpan;
                }
            }
            var current_excerpt = '';
            var childNodes = Array.from(targetNode.childNodes);
            for (var i = 0; i < childNodes.length; i++) {
                var node = childNodes[i];
                if (node.nodeType === ELEMENT_NODE && node.matches('sup.reference')) {
                    var cite_info = parseCitationFromSup(node);
                    if (!cite_info)
                        continue;
                    var current_cite_group = [cite_info];
                    var next_node_idx = i + 1;
                    while (next_node_idx < childNodes.length) {
                        var next_node = childNodes[next_node_idx];
                        if (next_node.nodeType === TEXT_NODE && ((_a = next_node.textContent) === null || _a === void 0 ? void 0 : _a.trim()) === '') {
                            next_node_idx++;
                            continue;
                        }
                        if (next_node.nodeType === ELEMENT_NODE && next_node.matches('sup.reference')) {
                            var next_cite = parseCitationFromSup(next_node);
                            if (next_cite) {
                                current_cite_group.push(next_cite);
                                i = next_node_idx;
                            }
                        }
                        else {
                            break;
                        }
                        next_node_idx++;
                    }
                    var excerpt = normalizeWhitespace(current_excerpt);
                    global_group_id++;
                    for (var _i = 0, current_cite_group_1 = current_cite_group; _i < current_cite_group_1.length; _i++) {
                        var c_info = current_cite_group_1[_i];
                        var cite_text_clean = c_info.text.replace(/[[\]]/g, '');
                        var cite_numbers = (cite_text_clean.match(/\d+/g) || []).map(Number);
                        for (var _b = 0, cite_numbers_1 = cite_numbers; _b < cite_numbers_1.length; _b++) {
                            var cite_num = cite_numbers_1[_b];
                            appearances.push({
                                cite_num: cite_num,
                                href: c_info.href,
                                cite_ref: c_info.cite_ref,
                                excerpt: excerpt,
                                groupId: global_group_id,
                                order: appearances.length,
                                section: section,
                            });
                        }
                    }
                    current_excerpt = '';
                }
                else {
                    current_excerpt += node.textContent || '';
                }
            }
        });
        return appearances;
    }
    function extractReferences(doc) {
        var references = {};
        doc.querySelectorAll('li[id^="cite_note-"]').forEach(function (item) {
            var _a, _b;
            var cite_id = item.id;
            var ref_name = null;
            var match = cite_id.match(/cite_note-(.+)-\d+$/);
            if (match) {
                ref_name = match[1] || null;
            }
            var backlink_span = item.querySelector('span.mw-cite-backlink');
            if (!backlink_span)
                return;
            var ref_text_span = item.querySelector('span.reference-text');
            var source_url = null;
            var archive_url = null;
            var raw_text = '';
            if (ref_text_span) {
                var clonedSpan = ref_text_span.cloneNode(true);
                clonedSpan
                    .querySelectorAll("style, link[rel='mw-deduplicated-inline-style']")
                    .forEach(function (el) { return el.remove(); });
                clonedSpan.querySelectorAll('li, p, div, br').forEach(function (el) {
                    el.before(' ');
                });
                raw_text = normalizeWhitespace(clonedSpan.textContent || '');
            }
            if (ref_text_span) {
                ref_text_span.querySelectorAll('a.external.text').forEach(function (link) {
                    var url = link.href;
                    if (url.includes('archive.') ||
                        url.includes('webcitation.org') ||
                        url.includes('ghostarchive.org')) {
                        if (!archive_url)
                            archive_url = url;
                    }
                    else {
                        if (!source_url)
                            source_url = url;
                    }
                });
            }
            var backlinks = backlink_span.querySelectorAll('a[href^="#cite_ref-"]');
            var letters = [];
            var hrefs = [];
            if (backlinks.length === 1) {
                hrefs.push(stripHash((_b = (_a = backlinks[0]) === null || _a === void 0 ? void 0 : _a.getAttribute('href')) !== null && _b !== void 0 ? _b : null));
            }
            else {
                backlinks.forEach(function (link) {
                    var _a;
                    var href = stripHash(link.getAttribute('href'));
                    var b_tag = link.querySelector('b');
                    if (b_tag) {
                        var letter = ((_a = b_tag.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || '';
                        if (letter && !['', '^', 'Jump up', 'Jump up to:'].includes(letter)) {
                            letters.push(letter);
                            hrefs.push(href);
                        }
                    }
                });
            }
            references[cite_id] = {
                name: ref_name,
                letters: letters,
                hrefs: hrefs,
                source_url: source_url,
                archive_url: archive_url,
                raw_text: raw_text,
            };
        });
        return references;
    }
    function buildOrderedReferences(appearances, reference_metadata) {
        var _a;
        var href_to_appearances = {};
        appearances.forEach(function (app) {
            var _a;
            if (!href_to_appearances[app.href]) {
                href_to_appearances[app.href] = [];
            }
            (_a = href_to_appearances[app.href]) === null || _a === void 0 ? void 0 : _a.push(app);
        });
        Object.values(href_to_appearances).forEach(function (apps) { return apps.sort(function (a, b) { return a.order - b.order; }); });
        var output = [];
        var _loop_1 = function (cite_id, metadata) {
            var matching_apps = href_to_appearances[cite_id] || [];
            if (matching_apps.length === 0)
                return "continue";
            var ref_num = ((_a = matching_apps[0]) === null || _a === void 0 ? void 0 : _a.cite_num) || 0;
            if (metadata.letters.length === 0) {
                var href = metadata.hrefs[0] || '';
                var app = matching_apps[0];
                output.push({
                    cite_id: cite_id,
                    number: ref_num,
                    name: metadata.name,
                    letter: null,
                    href: href,
                    excerpt: (app === null || app === void 0 ? void 0 : app.excerpt) || '',
                    groupId: app === null || app === void 0 ? void 0 : app.groupId,
                    order: (app === null || app === void 0 ? void 0 : app.order) !== undefined ? app.order : Infinity,
                    source_url: metadata.source_url,
                    archive_url: metadata.archive_url,
                    raw_text: metadata.raw_text,
                    section: (app === null || app === void 0 ? void 0 : app.section) || '',
                });
            }
            else {
                metadata.letters.forEach(function (letter, i) {
                    var href = metadata.hrefs[i] || '';
                    var app = matching_apps.find(function (a) { return a.cite_ref === href; });
                    output.push({
                        cite_id: cite_id,
                        number: ref_num,
                        name: metadata.name,
                        letter: letter,
                        href: href,
                        excerpt: (app === null || app === void 0 ? void 0 : app.excerpt) || '',
                        groupId: app === null || app === void 0 ? void 0 : app.groupId,
                        order: (app === null || app === void 0 ? void 0 : app.order) !== undefined ? app.order : Infinity,
                        source_url: metadata.source_url,
                        archive_url: metadata.archive_url,
                        raw_text: metadata.raw_text,
                        section: (app === null || app === void 0 ? void 0 : app.section) || '',
                    });
                });
            }
        };
        for (var _i = 0, _b = Object.entries(reference_metadata); _i < _b.length; _i++) {
            var _c = _b[_i], cite_id = _c[0], metadata = _c[1];
            _loop_1(cite_id, metadata);
        }
        return output.sort(function (a, b) { return a.order - b.order; });
    }

    function groupByExcerpt(references) {
        var groups = new Map();
        for (var _i = 0, references_1 = references; _i < references_1.length; _i++) {
            var ref = references_1[_i];
            var key = ref.groupId !== undefined ? String(ref.groupId) : "idx-".concat(ref.order);
            var existing = groups.get(key);
            if (existing) {
                existing.push(ref);
            }
            else {
                groups.set(key, [ref]);
            }
        }
        return groups;
    }
    function sampleReferences(ordered_references, sampleValue, sampleMode, minCitations) {
        var groups = groupByExcerpt(ordered_references);
        if (minCitations > 1) {
            var filtered_1 = new Map();
            groups.forEach(function (refs, groupId) {
                if (refs.length >= minCitations) {
                    filtered_1.set(groupId, refs);
                }
            });
            groups = filtered_1;
            ordered_references = Array.from(groups.values())
                .flat()
                .sort(function (a, b) { return a.order - b.order; });
        }
        var groupEntries = Array.from(groups.entries());
        var totalGroups = groupEntries.length;
        if (sampleValue && sampleValue > 0) {
            var targetGroups = totalGroups;
            if (sampleMode === 'percent') {
                var percent = Math.min(sampleValue, 100);
                targetGroups = Math.round(totalGroups * (percent / 100));
            }
            else {
                targetGroups = sampleValue;
            }
            targetGroups = Math.min(Math.max(targetGroups, 1), totalGroups);
            if (targetGroups < totalGroups) {
                var sampledRefList = [];
                var step = totalGroups / targetGroups;
                for (var i = 0; i < targetGroups; i++) {
                    var start = Math.floor(i * step);
                    var end = Math.floor((i + 1) * step);
                    var safeEnd = Math.min(end, totalGroups);
                    var randomIdx = Math.floor(start + Math.random() * (safeEnd - start));
                    var entry = groupEntries[randomIdx];
                    if (entry) {
                        sampledRefList.push.apply(sampledRefList, entry[1]);
                    }
                }
                ordered_references = sampledRefList.sort(function (a, b) { return a.order - b.order; });
            }
        }
        return {
            references: ordered_references,
            totalGroups: totalGroups,
        };
    }

    function truncateUrl(url, maxLen) {
        if (maxLen === void 0) { maxLen = 30; }
        if (!url)
            return "";
        try {
            var parsed = new URL(url);
            var domain = parsed.hostname;
            if (domain.startsWith("www.")) {
                domain = domain.substring(4);
            }
            if (domain.length > maxLen) {
                domain = domain.substring(0, maxLen - 1) + "…";
            }
            return "[".concat(url, " ").concat(domain, "]");
        }
        catch (_a) {
            return "[".concat(url, " ").concat(url, "]");
        }
    }
    function generateWikitextTable(references, article_url, revid, options) {
        if (options === void 0) { options = {}; }
        var _a = options.originalTotalRefs, originalTotalRefs = _a === void 0 ? 0 : _a, _b = options.originalTotalExcerpts, originalTotalExcerpts = _b === void 0 ? 0 : _b, _c = options.useSym, useSym = _c === void 0 ? true : _c, _d = options.minCitations, minCitations = _d === void 0 ? 1 : _d, _e = options.collapsed, collapsed = _e === void 0 ? true : _e, _f = options.includeSectionHeadings, includeSectionHeadings = _f === void 0 ? false : _f;
        var lines = [];
        var unique_refs = new Set(references.map(function (ref) { return ref.number; })).size;
        var total_citations_in_sample = references.length;
        var current_excerpts_count = new Set(references.map(function (ref) { return ref.groupId; }))
            .size;
        var isSampled = current_excerpts_count < originalTotalExcerpts;
        var passageType = minCitations > 1 ? "passages with ".concat(minCitations, "+ citations") : "passages";
        if (isSampled) {
            var percentExcerpts = ((current_excerpts_count / originalTotalExcerpts) *
                100).toFixed(1);
            var percentCitations = ((total_citations_in_sample / originalTotalRefs) *
                100).toFixed(1);
            lines.push("This table lists ".concat(current_excerpts_count, " random ").concat(passageType, " from throughout the article (").concat(percentExcerpts, "% of ").concat(originalTotalExcerpts, " total ").concat(minCitations > 1
                ? "passages with ".concat(minCitations, "+ citations")
                : "passages", ")."));
            lines.push("These passages contain ".concat(total_citations_in_sample, " inline citations (").concat(percentCitations, "% of ").concat(originalTotalRefs, " in the article). Generated with the [[User:Anne drew/Veracity|Veracity]] user script. ~~~~"));
        }
        else {
            lines.push("This table lists all ".concat(current_excerpts_count, " ").concat(passageType, " in the article (containing ").concat(total_citations_in_sample, " inline citations from ").concat(unique_refs, " unique sources)."));
            lines.push("Generated with the [[User:Anne drew/Veracity|Veracity]] user script. ~~~~");
        }
        lines.push("");
        var tableClasses = collapsed
            ? "wikitable mw-collapsible mw-collapsed"
            : "wikitable mw-collapsible";
        lines.push("{| class=\"".concat(tableClasses, "\" id=\"veracity-table\""));
        lines.push("|-");
        lines.push("! Reference # !! Letter !! Source !! Archive !! Status !! Notes");
        var last_quoted_text = null;
        var last_section = null;
        references.forEach(function (ref) {
            if (includeSectionHeadings && ref.section !== last_section) {
                if (ref.section) {
                    lines.push('|- style="border-top: 3px solid var(--border-color-base, #a2a9b1);"');
                    lines.push("| colspan=\"6\" | '''".concat(ref.section, "'''"));
                }
                last_section = ref.section;
            }
            var current_excerpt = ref.excerpt || "";
            if (current_excerpt !== last_quoted_text) {
                if (current_excerpt) {
                    var escaped_text = current_excerpt
                        .replace(/\|/g, "{{!}}")
                        .replace(/\[\[/g, "&lsqb;&lsqb;")
                        .replace(/]]/g, "&rsqb;&rsqb;");
                    lines.push('|- style="border-top: 3px solid var(--border-color-base, #a2a9b1);"');
                    lines.push("| colspan=\"6\" | ".concat(escaped_text));
                }
                else if (last_quoted_text) {
                    lines.push('|- style="border-top: 3px solid var(--border-color-base, #a2a9b1);"');
                    lines.push("| colspan=\"6\" | ''No text found: citation may be in an infobox or table''");
                }
                last_quoted_text = current_excerpt;
            }
            lines.push("|-");
            var letter = ref.letter || "";
            var href = ref.href || "";
            var status;
            if (useSym) {
                status = "{{sym|?}}";
            }
            else {
                status = "⏳";
            }
            var escapedHref = href
                .replace(/'/g, "%27")
                .replace(/"/g, "%22")
                .replace(/\[/g, "%5B")
                .replace(/\]/g, "%5D")
                .replace(/\|/g, "%7C");
            var full_url = "".concat(article_url, "?oldid=").concat(revid, "#").concat(escapedHref);
            var ref_link = ref.number;
            var letter_link = "";
            if (letter) {
                letter_link = "[".concat(full_url, " ").concat(letter, "]");
            }
            else {
                ref_link = "[".concat(full_url, " ").concat(ref.number, "]");
            }
            var source_link = "";
            if (ref.source_url) {
                source_link = truncateUrl(ref.source_url);
            }
            else if (ref.raw_text) {
                var text = ref.raw_text.replace(/\n/g, " ");
                if (text.length > 100) {
                    text = text.substring(0, 99) + "…";
                }
                source_link = text;
            }
            var archive_link = truncateUrl(ref.archive_url);
            lines.push("| ".concat(ref_link, " || ").concat(letter_link, " || ").concat(source_link, " || ").concat(archive_link, "\n|| ").concat(status, " ||"));
        });
        lines.push("|}");
        return lines.join("\n");
    }

    (function () {
        function main() {
            return __awaiter(this, void 0, void 0, function () {
                var defaultTitle, namespace, userInput, e_1, articleTitle, sampleValue, sampleMode, useSym, minCitations, collapsed, includeSectionHeadings, article_url, result, doc, revid, appearances, reference_metadata, ordered_references, originalTotalRefs, _a, sampledReferences, totalGroups, wikitext, surface, wikEdActive, textarea, $textarea;
                var _b;
                return __generator(this, function (_c) {
                    switch (_c.label) {
                        case 0:
                            defaultTitle = '';
                            namespace = mw.config.get('wgNamespaceNumber');
                            if (namespace === 0) {
                                defaultTitle = String(mw.config.get('wgPageName')).replace(/_/g, ' ');
                            }
                            _c.label = 1;
                        case 1:
                            _c.trys.push([1, 3, , 4]);
                            return [4, showInputDialog(defaultTitle)];
                        case 2:
                            userInput = _c.sent();
                            return [3, 4];
                        case 3:
                            e_1 = _c.sent();
                            console.error(e_1);
                            return [2];
                        case 4:
                            articleTitle = userInput.articleTitle, sampleValue = userInput.sampleValue, sampleMode = userInput.sampleMode, useSym = userInput.useSym, minCitations = userInput.minCitations, collapsed = userInput.collapsed, includeSectionHeadings = userInput.includeSectionHeadings;
                            if (!articleTitle)
                                return [2];
                            article_url = "https://en.wikipedia.org/wiki/".concat(articleTitle.replace(/ /g, '_'));
                            return [4, fetchArticleHtml(articleTitle)];
                        case 5:
                            result = _c.sent();
                            if (!result)
                                return [2];
                            doc = result.doc, revid = result.revid;
                            appearances = extractArticleTextWithCitations(doc);
                            reference_metadata = extractReferences(doc);
                            ordered_references = buildOrderedReferences(appearances, reference_metadata);
                            originalTotalRefs = ordered_references.length;
                            _a = sampleReferences(ordered_references, sampleValue, sampleMode, minCitations), sampledReferences = _a.references, totalGroups = _a.totalGroups;
                            ordered_references = sampledReferences;
                            wikitext = generateWikitextTable(ordered_references, article_url, revid, {
                                originalTotalRefs: originalTotalRefs,
                                originalTotalExcerpts: totalGroups,
                                useSym: useSym,
                                minCitations: minCitations,
                                collapsed: collapsed,
                                includeSectionHeadings: includeSectionHeadings,
                            });
                            if (typeof ve !== 'undefined' && ((_b = ve.init) === null || _b === void 0 ? void 0 : _b.target)) {
                                surface = ve.init.target.getSurface();
                                if (surface) {
                                    if (surface.getMode() === 'source') {
                                        surface.getModel().getFragment().collapseToEnd().insertContent('\n' + wikitext);
                                        return [2];
                                    }
                                    else {
                                        alert('Veracity cannot insert wikitext into VisualEditor. The table has been copied to your clipboard - please switch to source editing mode to paste it.');
                                        navigator.clipboard.writeText(wikitext);
                                        return [2];
                                    }
                                }
                            }
                            wikEdActive = typeof wikEd !== 'undefined' && wikEd.useWikEd === true;
                            if (wikEdActive) {
                                wikEd.UpdateTextarea();
                            }
                            textarea = document.getElementById('wpTextbox1');
                            if (textarea) {
                                $textarea = $('#wpTextbox1');
                                try {
                                    $textarea.textSelection('encapsulateSelection', {
                                        peri: '\n' + wikitext,
                                        ownline: true,
                                    });
                                    if (wikEdActive) {
                                        wikEd.UpdateFrame();
                                    }
                                    return [2];
                                }
                                catch (_d) {
                                    if (wikEdActive) {
                                        textarea.value += '\n' + wikitext;
                                        wikEd.UpdateFrame();
                                        return [2];
                                    }
                                }
                            }
                            alert('Could not find a text editor. The table has been copied to your clipboard instead.');
                            navigator.clipboard.writeText(wikitext);
                            return [2];
                    }
                });
            });
        }
        mw.loader.using(['jquery', 'mediawiki.util']).done(function () {
            $(function () {
                var portletLink = mw.util.addPortletLink('p-tb', '#', 'Veracity', 'ca-veracity', 'Generate Veracity source verification table');
                if (portletLink) {
                    $(portletLink).on('click', function (e) {
                        e.preventDefault();
                        main();
                    });
                }
            });
        });
    })();

})();
// </nowiki>